Repository: dotnet/runtime
File: src/tools/illink/src/linker/Linker.Steps/MarkStep.cs (C#)

Code before:
        public MarkingHelpers MarkingHelpers => Context.MarkingHelpers;
        public Tracer Tracer => Context.Tracer;
        public EmbeddedXmlInfo EmbeddedXmlInfo => Context.EmbeddedXmlInfo;

        public virtual void Process(LinkContext context)
        {
            _context = context;
            _markContext = new MarkStepContext();
            _dynamicallyAccessedMembersTypeHierarchy = new DynamicallyAccessedMembersTypeHierarchy(_context, this);

            Initialize();
            Process();
            Complete();
        }

        protected virtual void Initialize()
        {
            InitializeCorelibAttributeXml();
            Context.Pipeline.InitializeMarkHandlers(Context, MarkContext);

            // Check for TypeMappingEntryAssembly override from Features
            AssemblyDefinition? startingAssembly = null;
            if (Context.Features.TryGetValue("System.Runtime.InteropServices.TypeMappingEntryAssembly", out string? assemblyNameString))
            {
                var assemblyName = AssemblyNameReference.Parse(assemblyNameString);
                startingAssembly = Context.TryResolve(assemblyName);
            }
            // If resolution fails, fall back to entry point assembly
            startingAssembly ??= Annotations.GetEntryPointAssembly();

            _typeMapHandler.Initialize(Context, this, startingAssembly);
            ProcessMarkedPending();
        }

        void InitializeCorelibAttributeXml()
        {
            // Pre-load corelib and process its attribute XML first. This is necessary because the
            // corelib attribute XML can contain modifications to other assemblies.
            // We could just mark it here, but the attribute processing isn't necessarily tied to marking,
            // so this would rely on implementation details of corelib.
            var coreLib = Context.TryResolve(PlatformAssemblies.CoreLib);
            if (coreLib == null)
                return;

            var xmlInfo = EmbeddedXmlInfo.ProcessAttributes(coreLib, Context);
            if (xmlInfo == null)
                return;

            // Because the attribute XML can reference other assemblies, they must go in the global store,
            // instead of the per-assembly stores.
            foreach (var (provider, annotations) in xmlInfo.CustomAttributes)

Review comment (suggestion):
If `Context.TryResolve` returns null (assembly not found), the code falls back to the entry point assembly without logging or warning. Consider adding a warning message when the specified TypeMappingEntryAssembly cannot be resolved, as this could indicate a configuration error that should be surfaced to users.
```suggestion
                startingAssembly = Context.TryResolve(assemblyName);
                if (startingAssembly is null)
                {
                    Context.LogWarning(
                        $"Could not resolve assembly '{assemblyNameString}' specified by the 'System.Runtime.InteropServices.TypeMappingEntryAssembly' feature. Falling back to the entry point assembly.",
                        origin: null);
                }
```

Code after:
        public MarkingHelpers MarkingHelpers => Context.MarkingHelpers;
        public Tracer Tracer => Context.Tracer;
        public EmbeddedXmlInfo EmbeddedXmlInfo => Context.EmbeddedXmlInfo;

        public virtual void Process(LinkContext context)
        {
            _context = context;
            _markContext = new MarkStepContext();
            _dynamicallyAccessedMembersTypeHierarchy = new DynamicallyAccessedMembersTypeHierarchy(_context, this);

            Initialize();
            Process();
            Complete();
        }

        protected virtual void Initialize()
        {
            InitializeCorelibAttributeXml();
            Context.Pipeline.InitializeMarkHandlers(Context, MarkContext);

            // Check for TypeMappingEntryAssembly override
            AssemblyDefinition? startingAssembly = null;
            if (Context.TypeMapEntryAssembly is not null)
            {
                var assemblyName = AssemblyNameReference.Parse(Context.TypeMapEntryAssembly);
                startingAssembly = Context.TryResolve(assemblyName);
            }
            // If resolution fails, fall back to entry point assembly
            startingAssembly ??= Annotations.GetEntryPointAssembly();

            _typeMapHandler.Initialize(Context, this, startingAssembly);
            ProcessMarkedPending();
        }

        void InitializeCorelibAttributeXml()
        {
            // Pre-load corelib and process its attribute XML first. This is necessary because the
            // corelib attribute XML can contain modifications to other assemblies.
            // We could just mark it here, but the attribute processing isn't necessarily tied to marking,
            // so this would rely on implementation details of corelib.
            var coreLib = Context.TryResolve(PlatformAssemblies.CoreLib);
            if (coreLib == null)
                return;

            var xmlInfo = EmbeddedXmlInfo.ProcessAttributes(coreLib, Context);
            if (xmlInfo == null)
                return;

            // Because the attribute XML can reference other assemblies, they must go in the global store,
            // instead of the per-assembly stores.
            foreach (var (provider, annotations) in xmlInfo.CustomAttributes)