Dotsider.Core.Analysis
Classes
Section titled “Classes”Detects .NET apphost executables and locates their companion managed assemblies.
public static class ApphostDetectorCore analyzer that reads .NET assemblies, Webcil app assemblies, native binaries, and raw Wasm modules. It uses BCL metadata/PE readers where possible and routes runtime-native formats through dotsider’s format readers for IL, strings, symbols, disassembly, and size data.
public sealed class AssemblyAnalyzer : IDisposableCompares two assemblies and produces a detailed diff result. Uses dictionary-based O(n) matching by name.
public static class AssemblyDifferFormats an assembly’s full identity into a stable opaque string used as a graph node identifier and as a key for grouping TypeRefInfo entries by the full identity of their resolution scope.
public static class AssemblyIdentityFormatShared factory for opening assembly files. Handles apphosts (companion .dll redirect), single-file bundles (entry assembly extraction), Native AOT binaries, raw Wasm modules, and direct .dll/.exe loading. Returns an AssemblyOpenResult that preserves the distinction so callers can decide how to present each case (e.g. showing an apphost dialog).
public static class AssemblyLoaderResolves a “method or address” query against an AOT binary’s pre-ILC companion set and correlation index, producing the one CorrelationReport the CLI, session, and MCP surfaces all render. Attaches the companions on demand and builds the index once; ambiguity is surfaced as candidates, never resolved by picking the first match.
public static class CorrelationQueryBuilds the full transitive assembly dependency graph rooted at an analyzed assembly. Performs a breadth-first walk through each assembly’s AssemblyRefs, resolving children by full identity, deduping on Id, preserving edges for cycles and diamonds, and classifying unresolvable and identity-mismatched references as non-expanding leaf nodes. For .NET Framework roots the resolution routes through NetFxBinder so that nodes are keyed on the bound identity (post-redirect), collapsing two distinct requested versions onto a single graph node when policy redirects them to the same loaded version. Produces a DependencyGraphResult containing the public topology plus internal navigation metadata consumed only by the TUI.
public static class DependencyGraphBuilderReads an ILC dependency-graph DGML file, emitted when publishing a Native AOT project with
IlcGenerateDgmlFile. The format is a DirectedGraph document of nodes (id and
label) and links (source depends on target, with a reason). Node labels equal the node
names an mstat size report stores (MstatReader), which is how sizes join to
dependency chains.
Parsing streams the XML — the graphs run to hundreds of thousands of links — and never throws: unreadable files return null, and malformed nodes or links are skipped.
public static class DgmlReaderDiscovers system .NET installations and resolves shared framework assembly paths.
public static class DotNetRuntimeLocatorDecodes IL (Intermediate Language) method bodies into human-readable instruction sequences.
public sealed class IlDisassemblerResolves a metadata token from an IL instruction to an IlNavigationTarget describing what the token points to and where it lives.
public static class IlNavigationResolverResolves reference assemblies (e.g., System.Runtime, mscorlib) to their implementation assemblies (e.g., System.Private.CoreLib) by probing for type forwarding.
public static class ImplementationAssemblyResolverJoins pre-ILC managed methods to the native evidence of the AOT image they were compiled into: native symbols (via IlcNameDemangler, keyed from real companion metadata instead of the binary’s reduced recovered types) and mstat size rows. Built once, queried per-frame — every lookup is a dictionary hit.
public sealed class ManagedNativeIndexCompares two ILC size reports and explains where the bytes went: a hierarchical delta tree (assembly → namespace → type → method, beside the binary’s data categories), flat top contributors, and per-assembly / per-namespace aggregate deltas. Entries are matched by the build-stable identity keys of MstatSizeIndex, so overloads, folded MethodTables, and owner-grouped frozen objects compare correctly across builds.
public static class MstatDifferResolves a size-comparison input to its mstat report. A bare .mstat file is read
directly (detected by extension or by String) — an mstat is
itself a valid ECMA-335 assembly, so probing must come before any managed-assembly
interpretation); a Native AOT binary resolves through its sidecar discovery
(app.mstat beside the binary, or the ILC intermediate output tree). Anything else —
a managed assembly, a native binary without a size report — resolves to null.
public static class MstatLocatorReads an ILC size report (.mstat), the file IlcGenerateMstatFile emits when
publishing a Native AOT project. The report is itself a valid ECMA-335 assembly: its
assembly version carries the format version, and its data is encoded as IL instruction
streams in global methods named Methods, Types, Blobs, and (in newer
formats) RvaFields, FrozenObjects, ManifestResources, and
DeduplicatedMethods. Format 2.0+ also stores each entry’s dependency-graph node name
in a custom .names PE section; those names equal the node labels in the DGML graphs
IlcGenerateDgmlFile emits, which is how sizes join to dependency chains.
Malformed input never throws: unreadable files return null, and damage within an IL stream, including an impossible nested count, yields the entries parsed before the damage.
public static class MstatReaderThe normalized view of an ILC size report that every size consumer shares: raw rows aggregated under build-stable identity keys, one double-count policy for the 2.1+ detail sections, owner-based attribution for frozen objects, and per-assembly / per-namespace byte totals. SizeAnalyzer builds the Size Map from it, MstatDiffer compares two of them, and budget evaluation reads its aggregates — so a total shown in one place always equals the same total shown in another.
public sealed class MstatSizeIndexDetects Native AOT compiled .NET binaries by locating and validating the embedded ReadyToRun header. Every Native AOT image carries this header (signature “RTR\0”) so the runtime can find its module sections, but the signature bytes also occur as code immediates, so each candidate is validated against the field ranges the ILC toolchain actually emits before it is accepted.
public static class NativeAotDetectorReads a native binary’s symbols — function names, addresses, and sizes — from its debug information, demangling ILC names back to managed names and merging the overlapping records that different symbol sources produce. Windows native PDBs, Linux DWARF, and macOS dSYM/nlist each feed the same merge and demangle pipeline through NativeSourceMap); when no symbols exist, unwind data still yields function boundaries at lower fidelity. The public entry points that dispatch on image format are added as each reader lands.
public static class NativeSymbolReaderCLR-accurate .NET Framework assembly binder for both CLR generations. Consumes a NetFxBindingContext and produces a NetFxBindResult matching what the actual .NET Framework binder would do at runtime: framework unification + machine.config + publisher policy + app config (in CLR walk order, with later layers overriding earlier ones), then locate against the GAC (architecture-prioritized, strong-named only), then the framework runtime directory, then configured codeBase href (fail-fast), then the application base + private paths with culture-aware probing.
public static class NetFxBinderResolves assembly references by consulting the referencing assembly’s .deps.json
file to locate its NuGet dependencies in the NuGet global packages folder. This is the
probe step that makes library projects work — dotnet build does not copy NuGet
package assemblies next to a library’s bin output, but the .deps.json
manifest records the exact resolved package version and runtime asset path, matching
what the .NET host uses at runtime. Manifest paths are treated as untrusted and must
remain inside the selected package in the configured global packages folder.
public static class NuGetDepsJsonResolverOpens and analyzes a NuGet package (.nupkg) file. Reads package metadata from .nuspec and lists all contents.
public sealed class NuGetPackageAnalyzer : IDisposableLocates the pre-ILC build outputs of a Native AOT binary: the managed input assembly the compiler consumed, its portable PDB, and the mstat/DGML sidecars in the build’s intermediate tree.
public static class PreIlcSidecarDetectorResolves a “method or address” query against a ReadyToRun image and builds the one
ReadyToRunMethodReport the CLI, MCP, and session surfaces all render. A method
name, a 0x06… token, or a 0x… native address all resolve here; a value that is
both a valid token and a covered address is reported ambiguous rather than guessed. Methods
present in metadata but not precompiled resolve as IL-only rather than “not found”.
public static class ReadyToRunCorrelationQueryQueryable view of a ReadyToRun image’s precompiled methods: managed-method lookup by owning assembly identity and token, and reverse lookup by native address over the methods’ disjoint code ranges. The token is qualified by assembly name because a composite spans several assemblies whose tokens collide. Built once, every lookup a dictionary or binary-search hit.
public sealed class ReadyToRunIndexLaunches a .NET target and collects its runtime diagnostics. Uses the bundled trace host to keep TraceEvent outside the Native AOT process. Exposes events, counters, output, and lifecycle state to dotsider callers.
public sealed class RuntimeTracer : IDisposableReads .NET single-file bundles — detects the bundle signature, parses the manifest header, and extracts individual entries.
public static class SingleFileBundleReaderComputes IL code size per method and builds a hierarchical size tree for treemap visualization. For a Native AOT binary with an mstat sidecar the tree is built from the compiler’s size report instead: native code and MethodTable bytes per assembly, namespace, type, and method, plus the binary’s data categories. Without an mstat, the binary’s merged native symbols carry the tree.
public static class SizeAnalyzerResolves the total-size basis for a comparison of mstat inputs. The rule is shared by the
CLI, the MCP server, and the session protocol so a size figure never changes meaning
between surfaces: binaries measure file size on disk; a bare .mstat anywhere forces
mstat totals for both sides.
public static class SizeBasisResolverEvaluates size budgets against a size diff. Total budgets measure the caller’s basis-resolved totals (file size for binaries, mstat total for bare reports); namespace and assembly budgets always measure the diff’s mstat aggregates, with namespace targets covering their sub-namespaces. Each breach carries the scope’s top positive regressions — the rows that explain the growth.
public static class SizeBudgetEvaluatorReads a size-budget document: { "budgets": [ ... ] } where each entry is either a
spec string in the SizeBudgetParser grammar or an object
{ "name", "description", "scope", "max", "growth", "severity", "topN" } — the object
form is how a team names its budgets, downgrades one to a warning, or pins a per-budget
contributor count. Both forms mix freely in one document. The CLI’s --budget-file
and the MCP server’s inline budget JSON share this one parser.
public static class SizeBudgetFileParses size-budget spec strings. The grammar is
[scope:]limit(,limit)* where scope is total (the default), ns=NAME, or
asm=NAME, and each limit is max=SIZE or growth=SIZE|PERCENT. Sizes
accept b, kb, mb, and gb suffixes (1 kb = 1024 bytes; a bare
number is bytes); percentages (growth=1%) apply to growth only. Examples:
max=25mb · growth=1% · total:max=25mb,growth=50kb ·
ns=System.Text.Json:growth=10kb · asm=MyApp:max=2mb.
public static class SizeBudgetParserExtracts strings from .NET assemblies across three sources: the #US heap (user string literals), the #Strings heap (metadata identifiers), and raw printable character sequences from the binary.
public sealed class StringExtractorThe exception that is thrown when a package entry cannot be safely extracted beneath its destination directory.
public sealed class UnsafePackageEntryException : IOException, ISerializable