[ios-clr] Throw descriptive error when a stripped IL body is needed at runtime - #130025

Merged
kotlarmilos merged 11 commits into
dotnet:mainfrom
kotlarmilos:dev/stripped-il-error-handling
Jul 3, 2026
Merged

[ios-clr] Throw descriptive error when a stripped IL body is needed at runtime#130025
kotlarmilos merged 11 commits into
dotnet:mainfrom
kotlarmilos:dev/stripped-il-error-handling

Conversation

@kotlarmilos

@kotlarmiloskotlarmilos commented Jun 30, 2026

Copy link
Copy Markdown
Member

Description

When crossgen2 is run with --strip-il-bodies, method bodies that were precompiled and are not expected to be needed at runtime are replaced with a minimal "ldnull; throw" stub. On a runtime without a JIT fallback, if such a method is unexpectedly compiled at runtime the stub surfaces as an opaque NullReferenceException, which gives no indication that the real cause is a stripped IL body. This change detects the stub on the per-method compile path and throws a descriptive error instead, so the failure points at the actual problem. It complements the existing image-level guards: the load-time rejection of stripped images on a JIT runtime in readytoruninfo.cpp, and the eager-fixup fail-fast in ceeload.cpp that fires when a failed fixup disables all ReadyToRun code. Those guards cover whole-image configurations, while this one covers a single method that is lazily compiled while ReadyToRun is otherwise live, which is the case behind #129813.

…t runtime
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves diagnostics for ReadyToRun images produced with --strip-il-bodies by detecting the minimal “stripped IL” stub at per-method compile time and throwing a descriptive BadImageFormatException instead of surfacing an opaque NullReferenceException from executing ldnull; throw.

Changes:

  • Detect the stripped-IL stub (ldnull; throw) during metadata IL header decode for ReadyToRun modules with stripped IL bodies and throw COR_E_BADIMAGEFORMAT with a dedicated BFA message.
  • Add a new BFA_STRIPPED_IL_BODY resource ID and corresponding user-facing error string.
Show a summary per file
FileDescription
src/coreclr/vm/prestub.cppAdds a per-method stripped-IL stub detection and throws a targeted BadImageFormatException.
src/coreclr/dlls/mscorrc/resource.hIntroduces BFA_STRIPPED_IL_BODY resource identifier.
src/coreclr/dlls/mscorrc/mscorrc.rcAdds the new error message string for BFA_STRIPPED_IL_BODY.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 1

Comment threadsrc/coreclr/vm/prestub.cpp
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 09:35
@kotlarmiloskotlarmilos added this to the 11.0.0 milestone Jun 30, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment threadsrc/coreclr/vm/prestub.cpp Outdated
Emit an intentionally invalid IL sentinel (illegal two-byte opcode
0xFE 0x24) for stripped method bodies instead of 'ldnull; throw', and
match that exact sentinel in the runtime. The previous stub collided
with a real 'throw null;' method body, which could trigger a false
BadImageFormatException if such a method ever needed to be JITted.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 12:44
kotlarmilosand others added 2 commits June 30, 2026 14:50
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp Outdated
CopilotAI review requested due to automatic review settings June 30, 2026 12:53

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
Comment threadsrc/coreclr/dlls/mscorrc/mscorrc.rc Outdated
…eedback
- prestub.cpp: EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE instead of throw;
named sentinel constants; comment covers JIT and interpreter
- Remove now-unused BFA_STRIPPED_IL_BODY resource
- CopiedMethodILNode: clarify sentinel comment
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 2, 2026 08:38
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
CopilotAI review requested due to automatic review settings July 2, 2026 08:46

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
kotlarmilos added a commit that referenced this pull request Jul 2, 2026
## Description
The `--strip-il-bodies` optimization in crossgen2 is applied when
building the composite ReadyToRun images that ship in the Apple mobile
runtime packs, and in #129813 it regressed by stripping the IL of
non-async `Task`/`ValueTask`-returning methods. That IL is still needed,
because with runtime-async enabled the runtime compiles a runtime-async
variant of such a method from its IL, so replacing it with a `ldnull`
throw stub threw `NullReferenceException` on the mobile packs until
#129884 narrowed the pass via `MayNeedILAtRuntime`.
This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that
inspect the emitted component MSIL to assert every branch of the strip
logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning
methods, a generic method, and a method on a generic type keep their IL,
while plain methods and async `Task<T>`/`ValueTask` methods are still
stripped.
TODO: This PR should be aligned with
#130025
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kotlarmilosand others added 2 commits July 2, 2026 15:28
… 0x24 stub
PR dotnet#130025 changes the crossgen2 --strip-il-bodies stub from ldnull; throw
(0x14 0x7A) to an invalid opcode (0xFE 0x24). Update the regression test
added in PR dotnet#130075 to check for the new sentinel bytes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kotlarmilos
kotlarmilos merged commit 6585d1c into dotnet:mainJul 3, 2026
111 checks passed
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
## Description
The `--strip-il-bodies` optimization in crossgen2 is applied when
building the composite ReadyToRun images that ship in the Apple mobile
runtime packs, and in #129813 it regressed by stripping the IL of
non-async `Task`/`ValueTask`-returning methods. That IL is still needed,
because with runtime-async enabled the runtime compiles a runtime-async
variant of such a method from its IL, so replacing it with a `ldnull`
throw stub threw `NullReferenceException` on the mobile packs until
#129884 narrowed the pass via `MayNeedILAtRuntime`.
This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that
inspect the emitted component MSIL to assert every branch of the strip
logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning
methods, a generic method, and a method on a generic type keep their IL,
while plain methods and async `Task<T>`/`ValueTask` methods are still
stripped.
TODO: This PR should be aligned with
#130025
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
…t runtime (#130025)
## Description
When crossgen2 is run with --strip-il-bodies, method bodies that were
precompiled and are not expected to be needed at runtime are replaced
with a minimal "ldnull; throw" stub. On a runtime without a JIT
fallback, if such a method is unexpectedly compiled at runtime the stub
surfaces as an opaque NullReferenceException, which gives no indication
that the real cause is a stripped IL body. This change detects the stub
on the per-method compile path and throws a descriptive error instead,
so the failure points at the actual problem. It complements the existing
image-level guards: the load-time rejection of stripped images on a JIT
runtime in readytoruninfo.cpp, and the eager-fixup fail-fast in
ceeload.cpp that fires when a failed fixup disables all ReadyToRun code.
Those guards cover whole-image configurations, while this one covers a
single method that is lazily compiled while ReadyToRun is otherwise
live, which is the case behind #129813.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@kotlarmilos@BrzVlad@jakobbotsch
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

[ios-clr] Throw descriptive error when a stripped IL body is needed at runtime - #130025

Merged
kotlarmilos merged 11 commits into
dotnet:mainfrom
kotlarmilos:dev/stripped-il-error-handling
Jul 3, 2026
Merged

[ios-clr] Throw descriptive error when a stripped IL body is needed at runtime#130025
kotlarmilos merged 11 commits into
dotnet:mainfrom
kotlarmilos:dev/stripped-il-error-handling

Conversation

@kotlarmilos

@kotlarmiloskotlarmilos commented Jun 30, 2026

Copy link
Copy Markdown
Member

Description

When crossgen2 is run with --strip-il-bodies, method bodies that were precompiled and are not expected to be needed at runtime are replaced with a minimal "ldnull; throw" stub. On a runtime without a JIT fallback, if such a method is unexpectedly compiled at runtime the stub surfaces as an opaque NullReferenceException, which gives no indication that the real cause is a stripped IL body. This change detects the stub on the per-method compile path and throws a descriptive error instead, so the failure points at the actual problem. It complements the existing image-level guards: the load-time rejection of stripped images on a JIT runtime in readytoruninfo.cpp, and the eager-fixup fail-fast in ceeload.cpp that fires when a failed fixup disables all ReadyToRun code. Those guards cover whole-image configurations, while this one covers a single method that is lazily compiled while ReadyToRun is otherwise live, which is the case behind #129813.

…t runtime
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves diagnostics for ReadyToRun images produced with --strip-il-bodies by detecting the minimal “stripped IL” stub at per-method compile time and throwing a descriptive BadImageFormatException instead of surfacing an opaque NullReferenceException from executing ldnull; throw.

Changes:

  • Detect the stripped-IL stub (ldnull; throw) during metadata IL header decode for ReadyToRun modules with stripped IL bodies and throw COR_E_BADIMAGEFORMAT with a dedicated BFA message.
  • Add a new BFA_STRIPPED_IL_BODY resource ID and corresponding user-facing error string.
Show a summary per file
FileDescription
src/coreclr/vm/prestub.cppAdds a per-method stripped-IL stub detection and throws a targeted BadImageFormatException.
src/coreclr/dlls/mscorrc/resource.hIntroduces BFA_STRIPPED_IL_BODY resource identifier.
src/coreclr/dlls/mscorrc/mscorrc.rcAdds the new error message string for BFA_STRIPPED_IL_BODY.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 1

Comment threadsrc/coreclr/vm/prestub.cpp
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 09:35
@kotlarmiloskotlarmilos added this to the 11.0.0 milestone Jun 30, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment threadsrc/coreclr/vm/prestub.cpp Outdated
Emit an intentionally invalid IL sentinel (illegal two-byte opcode
0xFE 0x24) for stripped method bodies instead of 'ldnull; throw', and
match that exact sentinel in the runtime. The previous stub collided
with a real 'throw null;' method body, which could trigger a false
BadImageFormatException if such a method ever needed to be JITted.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 12:44
kotlarmilosand others added 2 commits June 30, 2026 14:50
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp Outdated
CopilotAI review requested due to automatic review settings June 30, 2026 12:53

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
Comment threadsrc/coreclr/dlls/mscorrc/mscorrc.rc Outdated
…eedback
- prestub.cpp: EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE instead of throw;
named sentinel constants; comment covers JIT and interpreter
- Remove now-unused BFA_STRIPPED_IL_BODY resource
- CopiedMethodILNode: clarify sentinel comment
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 2, 2026 08:38
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
CopilotAI review requested due to automatic review settings July 2, 2026 08:46

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
kotlarmilos added a commit that referenced this pull request Jul 2, 2026
## Description
The `--strip-il-bodies` optimization in crossgen2 is applied when
building the composite ReadyToRun images that ship in the Apple mobile
runtime packs, and in #129813 it regressed by stripping the IL of
non-async `Task`/`ValueTask`-returning methods. That IL is still needed,
because with runtime-async enabled the runtime compiles a runtime-async
variant of such a method from its IL, so replacing it with a `ldnull`
throw stub threw `NullReferenceException` on the mobile packs until
#129884 narrowed the pass via `MayNeedILAtRuntime`.
This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that
inspect the emitted component MSIL to assert every branch of the strip
logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning
methods, a generic method, and a method on a generic type keep their IL,
while plain methods and async `Task<T>`/`ValueTask` methods are still
stripped.
TODO: This PR should be aligned with
#130025
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kotlarmilosand others added 2 commits July 2, 2026 15:28
… 0x24 stub
PR dotnet#130025 changes the crossgen2 --strip-il-bodies stub from ldnull; throw
(0x14 0x7A) to an invalid opcode (0xFE 0x24). Update the regression test
added in PR dotnet#130075 to check for the new sentinel bytes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kotlarmilos
kotlarmilos merged commit 6585d1c into dotnet:mainJul 3, 2026
111 checks passed
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
## Description
The `--strip-il-bodies` optimization in crossgen2 is applied when
building the composite ReadyToRun images that ship in the Apple mobile
runtime packs, and in #129813 it regressed by stripping the IL of
non-async `Task`/`ValueTask`-returning methods. That IL is still needed,
because with runtime-async enabled the runtime compiles a runtime-async
variant of such a method from its IL, so replacing it with a `ldnull`
throw stub threw `NullReferenceException` on the mobile packs until
#129884 narrowed the pass via `MayNeedILAtRuntime`.
This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that
inspect the emitted component MSIL to assert every branch of the strip
logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning
methods, a generic method, and a method on a generic type keep their IL,
while plain methods and async `Task<T>`/`ValueTask` methods are still
stripped.
TODO: This PR should be aligned with
#130025
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
…t runtime (#130025)
## Description
When crossgen2 is run with --strip-il-bodies, method bodies that were
precompiled and are not expected to be needed at runtime are replaced
with a minimal "ldnull; throw" stub. On a runtime without a JIT
fallback, if such a method is unexpectedly compiled at runtime the stub
surfaces as an opaque NullReferenceException, which gives no indication
that the real cause is a stripped IL body. This change detects the stub
on the per-method compile path and throws a descriptive error instead,
so the failure points at the actual problem. It complements the existing
image-level guards: the load-time rejection of stripped images on a JIT
runtime in readytoruninfo.cpp, and the eager-fixup fail-fast in
ceeload.cpp that fires when a failed fixup disables all ReadyToRun code.
Those guards cover whole-image configurations, while this one covers a
single method that is lazily compiled while ReadyToRun is otherwise
live, which is the case behind #129813.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@kotlarmilos@BrzVlad@jakobbotsch
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[ios-clr] Throw descriptive error when a stripped IL body is needed at runtime - #130025

Merged
kotlarmilos merged 11 commits into
dotnet:mainfrom
kotlarmilos:dev/stripped-il-error-handling
Jul 3, 2026
Merged

[ios-clr] Throw descriptive error when a stripped IL body is needed at runtime#130025
kotlarmilos merged 11 commits into
dotnet:mainfrom
kotlarmilos:dev/stripped-il-error-handling

Conversation

@kotlarmilos

@kotlarmiloskotlarmilos commented Jun 30, 2026

Copy link
Copy Markdown
Member

Description

When crossgen2 is run with --strip-il-bodies, method bodies that were precompiled and are not expected to be needed at runtime are replaced with a minimal "ldnull; throw" stub. On a runtime without a JIT fallback, if such a method is unexpectedly compiled at runtime the stub surfaces as an opaque NullReferenceException, which gives no indication that the real cause is a stripped IL body. This change detects the stub on the per-method compile path and throws a descriptive error instead, so the failure points at the actual problem. It complements the existing image-level guards: the load-time rejection of stripped images on a JIT runtime in readytoruninfo.cpp, and the eager-fixup fail-fast in ceeload.cpp that fires when a failed fixup disables all ReadyToRun code. Those guards cover whole-image configurations, while this one covers a single method that is lazily compiled while ReadyToRun is otherwise live, which is the case behind #129813.

…t runtime
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves diagnostics for ReadyToRun images produced with --strip-il-bodies by detecting the minimal “stripped IL” stub at per-method compile time and throwing a descriptive BadImageFormatException instead of surfacing an opaque NullReferenceException from executing ldnull; throw.

Changes:

  • Detect the stripped-IL stub (ldnull; throw) during metadata IL header decode for ReadyToRun modules with stripped IL bodies and throw COR_E_BADIMAGEFORMAT with a dedicated BFA message.
  • Add a new BFA_STRIPPED_IL_BODY resource ID and corresponding user-facing error string.
Show a summary per file
FileDescription
src/coreclr/vm/prestub.cppAdds a per-method stripped-IL stub detection and throws a targeted BadImageFormatException.
src/coreclr/dlls/mscorrc/resource.hIntroduces BFA_STRIPPED_IL_BODY resource identifier.
src/coreclr/dlls/mscorrc/mscorrc.rcAdds the new error message string for BFA_STRIPPED_IL_BODY.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 1

Comment threadsrc/coreclr/vm/prestub.cpp
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 09:35
@kotlarmiloskotlarmilos added this to the 11.0.0 milestone Jun 30, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment threadsrc/coreclr/vm/prestub.cpp Outdated
Emit an intentionally invalid IL sentinel (illegal two-byte opcode
0xFE 0x24) for stripped method bodies instead of 'ldnull; throw', and
match that exact sentinel in the runtime. The previous stub collided
with a real 'throw null;' method body, which could trigger a false
BadImageFormatException if such a method ever needed to be JITted.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 12:44
kotlarmilosand others added 2 commits June 30, 2026 14:50
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp Outdated
CopilotAI review requested due to automatic review settings June 30, 2026 12:53

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
Comment threadsrc/coreclr/dlls/mscorrc/mscorrc.rc Outdated
…eedback
- prestub.cpp: EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE instead of throw;
named sentinel constants; comment covers JIT and interpreter
- Remove now-unused BFA_STRIPPED_IL_BODY resource
- CopiedMethodILNode: clarify sentinel comment
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 2, 2026 08:38
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
CopilotAI review requested due to automatic review settings July 2, 2026 08:46

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
kotlarmilos added a commit that referenced this pull request Jul 2, 2026
## Description
The `--strip-il-bodies` optimization in crossgen2 is applied when
building the composite ReadyToRun images that ship in the Apple mobile
runtime packs, and in #129813 it regressed by stripping the IL of
non-async `Task`/`ValueTask`-returning methods. That IL is still needed,
because with runtime-async enabled the runtime compiles a runtime-async
variant of such a method from its IL, so replacing it with a `ldnull`
throw stub threw `NullReferenceException` on the mobile packs until
#129884 narrowed the pass via `MayNeedILAtRuntime`.
This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that
inspect the emitted component MSIL to assert every branch of the strip
logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning
methods, a generic method, and a method on a generic type keep their IL,
while plain methods and async `Task<T>`/`ValueTask` methods are still
stripped.
TODO: This PR should be aligned with
#130025
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kotlarmilosand others added 2 commits July 2, 2026 15:28
… 0x24 stub
PR dotnet#130025 changes the crossgen2 --strip-il-bodies stub from ldnull; throw
(0x14 0x7A) to an invalid opcode (0xFE 0x24). Update the regression test
added in PR dotnet#130075 to check for the new sentinel bytes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kotlarmilos
kotlarmilos merged commit 6585d1c into dotnet:mainJul 3, 2026
111 checks passed
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
## Description
The `--strip-il-bodies` optimization in crossgen2 is applied when
building the composite ReadyToRun images that ship in the Apple mobile
runtime packs, and in #129813 it regressed by stripping the IL of
non-async `Task`/`ValueTask`-returning methods. That IL is still needed,
because with runtime-async enabled the runtime compiles a runtime-async
variant of such a method from its IL, so replacing it with a `ldnull`
throw stub threw `NullReferenceException` on the mobile packs until
#129884 narrowed the pass via `MayNeedILAtRuntime`.
This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that
inspect the emitted component MSIL to assert every branch of the strip
logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning
methods, a generic method, and a method on a generic type keep their IL,
while plain methods and async `Task<T>`/`ValueTask` methods are still
stripped.
TODO: This PR should be aligned with
#130025
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
…t runtime (#130025)
## Description
When crossgen2 is run with --strip-il-bodies, method bodies that were
precompiled and are not expected to be needed at runtime are replaced
with a minimal "ldnull; throw" stub. On a runtime without a JIT
fallback, if such a method is unexpectedly compiled at runtime the stub
surfaces as an opaque NullReferenceException, which gives no indication
that the real cause is a stripped IL body. This change detects the stub
on the per-method compile path and throws a descriptive error instead,
so the failure points at the actual problem. It complements the existing
image-level guards: the load-time rejection of stripped images on a JIT
runtime in readytoruninfo.cpp, and the eager-fixup fail-fast in
ceeload.cpp that fires when a failed fixup disables all ReadyToRun code.
Those guards cover whole-image configurations, while this one covers a
single method that is lazily compiled while ReadyToRun is otherwise
live, which is the case behind #129813.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@kotlarmilos@BrzVlad@jakobbotsch
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[ios-clr] Throw descriptive error when a stripped IL body is needed at runtime - #130025

Merged
kotlarmilos merged 11 commits into
dotnet:mainfrom
kotlarmilos:dev/stripped-il-error-handling
Jul 3, 2026
Merged

[ios-clr] Throw descriptive error when a stripped IL body is needed at runtime#130025
kotlarmilos merged 11 commits into
dotnet:mainfrom
kotlarmilos:dev/stripped-il-error-handling

Conversation

@kotlarmilos

@kotlarmiloskotlarmilos commented Jun 30, 2026

Copy link
Copy Markdown
Member

Description

When crossgen2 is run with --strip-il-bodies, method bodies that were precompiled and are not expected to be needed at runtime are replaced with a minimal "ldnull; throw" stub. On a runtime without a JIT fallback, if such a method is unexpectedly compiled at runtime the stub surfaces as an opaque NullReferenceException, which gives no indication that the real cause is a stripped IL body. This change detects the stub on the per-method compile path and throws a descriptive error instead, so the failure points at the actual problem. It complements the existing image-level guards: the load-time rejection of stripped images on a JIT runtime in readytoruninfo.cpp, and the eager-fixup fail-fast in ceeload.cpp that fires when a failed fixup disables all ReadyToRun code. Those guards cover whole-image configurations, while this one covers a single method that is lazily compiled while ReadyToRun is otherwise live, which is the case behind #129813.

…t runtime
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves diagnostics for ReadyToRun images produced with --strip-il-bodies by detecting the minimal “stripped IL” stub at per-method compile time and throwing a descriptive BadImageFormatException instead of surfacing an opaque NullReferenceException from executing ldnull; throw.

Changes:

  • Detect the stripped-IL stub (ldnull; throw) during metadata IL header decode for ReadyToRun modules with stripped IL bodies and throw COR_E_BADIMAGEFORMAT with a dedicated BFA message.
  • Add a new BFA_STRIPPED_IL_BODY resource ID and corresponding user-facing error string.
Show a summary per file
FileDescription
src/coreclr/vm/prestub.cppAdds a per-method stripped-IL stub detection and throws a targeted BadImageFormatException.
src/coreclr/dlls/mscorrc/resource.hIntroduces BFA_STRIPPED_IL_BODY resource identifier.
src/coreclr/dlls/mscorrc/mscorrc.rcAdds the new error message string for BFA_STRIPPED_IL_BODY.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 1

Comment threadsrc/coreclr/vm/prestub.cpp
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 09:35
@kotlarmiloskotlarmilos added this to the 11.0.0 milestone Jun 30, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment threadsrc/coreclr/vm/prestub.cpp Outdated
Emit an intentionally invalid IL sentinel (illegal two-byte opcode
0xFE 0x24) for stripped method bodies instead of 'ldnull; throw', and
match that exact sentinel in the runtime. The previous stub collided
with a real 'throw null;' method body, which could trigger a false
BadImageFormatException if such a method ever needed to be JITted.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 12:44
kotlarmilosand others added 2 commits June 30, 2026 14:50
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp Outdated
CopilotAI review requested due to automatic review settings June 30, 2026 12:53

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
Comment threadsrc/coreclr/dlls/mscorrc/mscorrc.rc Outdated
…eedback
- prestub.cpp: EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE instead of throw;
named sentinel constants; comment covers JIT and interpreter
- Remove now-unused BFA_STRIPPED_IL_BODY resource
- CopiedMethodILNode: clarify sentinel comment
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 2, 2026 08:38
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
CopilotAI review requested due to automatic review settings July 2, 2026 08:46

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
kotlarmilos added a commit that referenced this pull request Jul 2, 2026
## Description
The `--strip-il-bodies` optimization in crossgen2 is applied when
building the composite ReadyToRun images that ship in the Apple mobile
runtime packs, and in #129813 it regressed by stripping the IL of
non-async `Task`/`ValueTask`-returning methods. That IL is still needed,
because with runtime-async enabled the runtime compiles a runtime-async
variant of such a method from its IL, so replacing it with a `ldnull`
throw stub threw `NullReferenceException` on the mobile packs until
#129884 narrowed the pass via `MayNeedILAtRuntime`.
This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that
inspect the emitted component MSIL to assert every branch of the strip
logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning
methods, a generic method, and a method on a generic type keep their IL,
while plain methods and async `Task<T>`/`ValueTask` methods are still
stripped.
TODO: This PR should be aligned with
#130025
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kotlarmilosand others added 2 commits July 2, 2026 15:28
… 0x24 stub
PR dotnet#130025 changes the crossgen2 --strip-il-bodies stub from ldnull; throw
(0x14 0x7A) to an invalid opcode (0xFE 0x24). Update the regression test
added in PR dotnet#130075 to check for the new sentinel bytes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kotlarmilos
kotlarmilos merged commit 6585d1c into dotnet:mainJul 3, 2026
111 checks passed
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
## Description
The `--strip-il-bodies` optimization in crossgen2 is applied when
building the composite ReadyToRun images that ship in the Apple mobile
runtime packs, and in #129813 it regressed by stripping the IL of
non-async `Task`/`ValueTask`-returning methods. That IL is still needed,
because with runtime-async enabled the runtime compiles a runtime-async
variant of such a method from its IL, so replacing it with a `ldnull`
throw stub threw `NullReferenceException` on the mobile packs until
#129884 narrowed the pass via `MayNeedILAtRuntime`.
This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that
inspect the emitted component MSIL to assert every branch of the strip
logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning
methods, a generic method, and a method on a generic type keep their IL,
while plain methods and async `Task<T>`/`ValueTask` methods are still
stripped.
TODO: This PR should be aligned with
#130025
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
…t runtime (#130025)
## Description
When crossgen2 is run with --strip-il-bodies, method bodies that were
precompiled and are not expected to be needed at runtime are replaced
with a minimal "ldnull; throw" stub. On a runtime without a JIT
fallback, if such a method is unexpectedly compiled at runtime the stub
surfaces as an opaque NullReferenceException, which gives no indication
that the real cause is a stripped IL body. This change detects the stub
on the per-method compile path and throws a descriptive error instead,
so the failure points at the actual problem. It complements the existing
image-level guards: the load-time rejection of stripped images on a JIT
runtime in readytoruninfo.cpp, and the eager-fixup fail-fast in
ceeload.cpp that fires when a failed fixup disables all ReadyToRun code.
Those guards cover whole-image configurations, while this one covers a
single method that is lazily compiled while ReadyToRun is otherwise
live, which is the case behind #129813.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@kotlarmilos@BrzVlad@jakobbotsch
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

[ios-clr] Throw descriptive error when a stripped IL body is needed at runtime - #130025

Merged
kotlarmilos merged 11 commits into
dotnet:mainfrom
kotlarmilos:dev/stripped-il-error-handling
Jul 3, 2026
Merged

[ios-clr] Throw descriptive error when a stripped IL body is needed at runtime#130025
kotlarmilos merged 11 commits into
dotnet:mainfrom
kotlarmilos:dev/stripped-il-error-handling

Conversation

@kotlarmilos

@kotlarmiloskotlarmilos commented Jun 30, 2026

Copy link
Copy Markdown
Member

Description

When crossgen2 is run with --strip-il-bodies, method bodies that were precompiled and are not expected to be needed at runtime are replaced with a minimal "ldnull; throw" stub. On a runtime without a JIT fallback, if such a method is unexpectedly compiled at runtime the stub surfaces as an opaque NullReferenceException, which gives no indication that the real cause is a stripped IL body. This change detects the stub on the per-method compile path and throws a descriptive error instead, so the failure points at the actual problem. It complements the existing image-level guards: the load-time rejection of stripped images on a JIT runtime in readytoruninfo.cpp, and the eager-fixup fail-fast in ceeload.cpp that fires when a failed fixup disables all ReadyToRun code. Those guards cover whole-image configurations, while this one covers a single method that is lazily compiled while ReadyToRun is otherwise live, which is the case behind #129813.

…t runtime
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves diagnostics for ReadyToRun images produced with --strip-il-bodies by detecting the minimal “stripped IL” stub at per-method compile time and throwing a descriptive BadImageFormatException instead of surfacing an opaque NullReferenceException from executing ldnull; throw.

Changes:

  • Detect the stripped-IL stub (ldnull; throw) during metadata IL header decode for ReadyToRun modules with stripped IL bodies and throw COR_E_BADIMAGEFORMAT with a dedicated BFA message.
  • Add a new BFA_STRIPPED_IL_BODY resource ID and corresponding user-facing error string.
Show a summary per file
FileDescription
src/coreclr/vm/prestub.cppAdds a per-method stripped-IL stub detection and throws a targeted BadImageFormatException.
src/coreclr/dlls/mscorrc/resource.hIntroduces BFA_STRIPPED_IL_BODY resource identifier.
src/coreclr/dlls/mscorrc/mscorrc.rcAdds the new error message string for BFA_STRIPPED_IL_BODY.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 1

Comment threadsrc/coreclr/vm/prestub.cpp
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 09:35
@kotlarmiloskotlarmilos added this to the 11.0.0 milestone Jun 30, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment threadsrc/coreclr/vm/prestub.cpp Outdated
Emit an intentionally invalid IL sentinel (illegal two-byte opcode
0xFE 0x24) for stripped method bodies instead of 'ldnull; throw', and
match that exact sentinel in the runtime. The previous stub collided
with a real 'throw null;' method body, which could trigger a false
BadImageFormatException if such a method ever needed to be JITted.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 12:44
kotlarmilosand others added 2 commits June 30, 2026 14:50
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp Outdated
CopilotAI review requested due to automatic review settings June 30, 2026 12:53

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
Comment threadsrc/coreclr/dlls/mscorrc/mscorrc.rc Outdated
…eedback
- prestub.cpp: EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE instead of throw;
named sentinel constants; comment covers JIT and interpreter
- Remove now-unused BFA_STRIPPED_IL_BODY resource
- CopiedMethodILNode: clarify sentinel comment
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 2, 2026 08:38
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
CopilotAI review requested due to automatic review settings July 2, 2026 08:46

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
kotlarmilos added a commit that referenced this pull request Jul 2, 2026
## Description
The `--strip-il-bodies` optimization in crossgen2 is applied when
building the composite ReadyToRun images that ship in the Apple mobile
runtime packs, and in #129813 it regressed by stripping the IL of
non-async `Task`/`ValueTask`-returning methods. That IL is still needed,
because with runtime-async enabled the runtime compiles a runtime-async
variant of such a method from its IL, so replacing it with a `ldnull`
throw stub threw `NullReferenceException` on the mobile packs until
#129884 narrowed the pass via `MayNeedILAtRuntime`.
This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that
inspect the emitted component MSIL to assert every branch of the strip
logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning
methods, a generic method, and a method on a generic type keep their IL,
while plain methods and async `Task<T>`/`ValueTask` methods are still
stripped.
TODO: This PR should be aligned with
#130025
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kotlarmilosand others added 2 commits July 2, 2026 15:28
… 0x24 stub
PR dotnet#130025 changes the crossgen2 --strip-il-bodies stub from ldnull; throw
(0x14 0x7A) to an invalid opcode (0xFE 0x24). Update the regression test
added in PR dotnet#130075 to check for the new sentinel bytes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kotlarmilos
kotlarmilos merged commit 6585d1c into dotnet:mainJul 3, 2026
111 checks passed
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
## Description
The `--strip-il-bodies` optimization in crossgen2 is applied when
building the composite ReadyToRun images that ship in the Apple mobile
runtime packs, and in #129813 it regressed by stripping the IL of
non-async `Task`/`ValueTask`-returning methods. That IL is still needed,
because with runtime-async enabled the runtime compiles a runtime-async
variant of such a method from its IL, so replacing it with a `ldnull`
throw stub threw `NullReferenceException` on the mobile packs until
#129884 narrowed the pass via `MayNeedILAtRuntime`.
This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that
inspect the emitted component MSIL to assert every branch of the strip
logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning
methods, a generic method, and a method on a generic type keep their IL,
while plain methods and async `Task<T>`/`ValueTask` methods are still
stripped.
TODO: This PR should be aligned with
#130025
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
…t runtime (#130025)
## Description
When crossgen2 is run with --strip-il-bodies, method bodies that were
precompiled and are not expected to be needed at runtime are replaced
with a minimal "ldnull; throw" stub. On a runtime without a JIT
fallback, if such a method is unexpectedly compiled at runtime the stub
surfaces as an opaque NullReferenceException, which gives no indication
that the real cause is a stripped IL body. This change detects the stub
on the per-method compile path and throws a descriptive error instead,
so the failure points at the actual problem. It complements the existing
image-level guards: the load-time rejection of stripped images on a JIT
runtime in readytoruninfo.cpp, and the eager-fixup fail-fast in
ceeload.cpp that fires when a failed fixup disables all ReadyToRun code.
Those guards cover whole-image configurations, while this one covers a
single method that is lazily compiled while ReadyToRun is otherwise
live, which is the case behind #129813.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@kotlarmilos@BrzVlad@jakobbotsch
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[ios-clr] Throw descriptive error when a stripped IL body is needed at runtime - #130025

Merged
kotlarmilos merged 11 commits into
dotnet:mainfrom
kotlarmilos:dev/stripped-il-error-handling
Jul 3, 2026
Merged

[ios-clr] Throw descriptive error when a stripped IL body is needed at runtime#130025
kotlarmilos merged 11 commits into
dotnet:mainfrom
kotlarmilos:dev/stripped-il-error-handling

Conversation

@kotlarmilos

@kotlarmiloskotlarmilos commented Jun 30, 2026

Copy link
Copy Markdown
Member

Description

When crossgen2 is run with --strip-il-bodies, method bodies that were precompiled and are not expected to be needed at runtime are replaced with a minimal "ldnull; throw" stub. On a runtime without a JIT fallback, if such a method is unexpectedly compiled at runtime the stub surfaces as an opaque NullReferenceException, which gives no indication that the real cause is a stripped IL body. This change detects the stub on the per-method compile path and throws a descriptive error instead, so the failure points at the actual problem. It complements the existing image-level guards: the load-time rejection of stripped images on a JIT runtime in readytoruninfo.cpp, and the eager-fixup fail-fast in ceeload.cpp that fires when a failed fixup disables all ReadyToRun code. Those guards cover whole-image configurations, while this one covers a single method that is lazily compiled while ReadyToRun is otherwise live, which is the case behind #129813.

…t runtime
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves diagnostics for ReadyToRun images produced with --strip-il-bodies by detecting the minimal “stripped IL” stub at per-method compile time and throwing a descriptive BadImageFormatException instead of surfacing an opaque NullReferenceException from executing ldnull; throw.

Changes:

  • Detect the stripped-IL stub (ldnull; throw) during metadata IL header decode for ReadyToRun modules with stripped IL bodies and throw COR_E_BADIMAGEFORMAT with a dedicated BFA message.
  • Add a new BFA_STRIPPED_IL_BODY resource ID and corresponding user-facing error string.
Show a summary per file
FileDescription
src/coreclr/vm/prestub.cppAdds a per-method stripped-IL stub detection and throws a targeted BadImageFormatException.
src/coreclr/dlls/mscorrc/resource.hIntroduces BFA_STRIPPED_IL_BODY resource identifier.
src/coreclr/dlls/mscorrc/mscorrc.rcAdds the new error message string for BFA_STRIPPED_IL_BODY.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 1

Comment threadsrc/coreclr/vm/prestub.cpp
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 09:35
@kotlarmiloskotlarmilos added this to the 11.0.0 milestone Jun 30, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment threadsrc/coreclr/vm/prestub.cpp Outdated
Emit an intentionally invalid IL sentinel (illegal two-byte opcode
0xFE 0x24) for stripped method bodies instead of 'ldnull; throw', and
match that exact sentinel in the runtime. The previous stub collided
with a real 'throw null;' method body, which could trigger a false
BadImageFormatException if such a method ever needed to be JITted.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 12:44
kotlarmilosand others added 2 commits June 30, 2026 14:50
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp Outdated
CopilotAI review requested due to automatic review settings June 30, 2026 12:53

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
Comment threadsrc/coreclr/dlls/mscorrc/mscorrc.rc Outdated
…eedback
- prestub.cpp: EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE instead of throw;
named sentinel constants; comment covers JIT and interpreter
- Remove now-unused BFA_STRIPPED_IL_BODY resource
- CopiedMethodILNode: clarify sentinel comment
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 2, 2026 08:38
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
CopilotAI review requested due to automatic review settings July 2, 2026 08:46

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
kotlarmilos added a commit that referenced this pull request Jul 2, 2026
## Description
The `--strip-il-bodies` optimization in crossgen2 is applied when
building the composite ReadyToRun images that ship in the Apple mobile
runtime packs, and in #129813 it regressed by stripping the IL of
non-async `Task`/`ValueTask`-returning methods. That IL is still needed,
because with runtime-async enabled the runtime compiles a runtime-async
variant of such a method from its IL, so replacing it with a `ldnull`
throw stub threw `NullReferenceException` on the mobile packs until
#129884 narrowed the pass via `MayNeedILAtRuntime`.
This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that
inspect the emitted component MSIL to assert every branch of the strip
logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning
methods, a generic method, and a method on a generic type keep their IL,
while plain methods and async `Task<T>`/`ValueTask` methods are still
stripped.
TODO: This PR should be aligned with
#130025
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kotlarmilosand others added 2 commits July 2, 2026 15:28
… 0x24 stub
PR dotnet#130025 changes the crossgen2 --strip-il-bodies stub from ldnull; throw
(0x14 0x7A) to an invalid opcode (0xFE 0x24). Update the regression test
added in PR dotnet#130075 to check for the new sentinel bytes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kotlarmilos
kotlarmilos merged commit 6585d1c into dotnet:mainJul 3, 2026
111 checks passed
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
## Description
The `--strip-il-bodies` optimization in crossgen2 is applied when
building the composite ReadyToRun images that ship in the Apple mobile
runtime packs, and in #129813 it regressed by stripping the IL of
non-async `Task`/`ValueTask`-returning methods. That IL is still needed,
because with runtime-async enabled the runtime compiles a runtime-async
variant of such a method from its IL, so replacing it with a `ldnull`
throw stub threw `NullReferenceException` on the mobile packs until
#129884 narrowed the pass via `MayNeedILAtRuntime`.
This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that
inspect the emitted component MSIL to assert every branch of the strip
logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning
methods, a generic method, and a method on a generic type keep their IL,
while plain methods and async `Task<T>`/`ValueTask` methods are still
stripped.
TODO: This PR should be aligned with
#130025
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
…t runtime (#130025)
## Description
When crossgen2 is run with --strip-il-bodies, method bodies that were
precompiled and are not expected to be needed at runtime are replaced
with a minimal "ldnull; throw" stub. On a runtime without a JIT
fallback, if such a method is unexpectedly compiled at runtime the stub
surfaces as an opaque NullReferenceException, which gives no indication
that the real cause is a stripped IL body. This change detects the stub
on the per-method compile path and throws a descriptive error instead,
so the failure points at the actual problem. It complements the existing
image-level guards: the load-time rejection of stripped images on a JIT
runtime in readytoruninfo.cpp, and the eager-fixup fail-fast in
ceeload.cpp that fires when a failed fixup disables all ReadyToRun code.
Those guards cover whole-image configurations, while this one covers a
single method that is lazily compiled while ReadyToRun is otherwise
live, which is the case behind #129813.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@kotlarmilos@BrzVlad@jakobbotsch
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[ios-clr] Throw descriptive error when a stripped IL body is needed at runtime - #130025

Merged
kotlarmilos merged 11 commits into
dotnet:mainfrom
kotlarmilos:dev/stripped-il-error-handling
Jul 3, 2026
Merged

[ios-clr] Throw descriptive error when a stripped IL body is needed at runtime#130025
kotlarmilos merged 11 commits into
dotnet:mainfrom
kotlarmilos:dev/stripped-il-error-handling

Conversation

@kotlarmilos

@kotlarmiloskotlarmilos commented Jun 30, 2026

Copy link
Copy Markdown
Member

Description

When crossgen2 is run with --strip-il-bodies, method bodies that were precompiled and are not expected to be needed at runtime are replaced with a minimal "ldnull; throw" stub. On a runtime without a JIT fallback, if such a method is unexpectedly compiled at runtime the stub surfaces as an opaque NullReferenceException, which gives no indication that the real cause is a stripped IL body. This change detects the stub on the per-method compile path and throws a descriptive error instead, so the failure points at the actual problem. It complements the existing image-level guards: the load-time rejection of stripped images on a JIT runtime in readytoruninfo.cpp, and the eager-fixup fail-fast in ceeload.cpp that fires when a failed fixup disables all ReadyToRun code. Those guards cover whole-image configurations, while this one covers a single method that is lazily compiled while ReadyToRun is otherwise live, which is the case behind #129813.

…t runtime
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves diagnostics for ReadyToRun images produced with --strip-il-bodies by detecting the minimal “stripped IL” stub at per-method compile time and throwing a descriptive BadImageFormatException instead of surfacing an opaque NullReferenceException from executing ldnull; throw.

Changes:

  • Detect the stripped-IL stub (ldnull; throw) during metadata IL header decode for ReadyToRun modules with stripped IL bodies and throw COR_E_BADIMAGEFORMAT with a dedicated BFA message.
  • Add a new BFA_STRIPPED_IL_BODY resource ID and corresponding user-facing error string.
Show a summary per file
FileDescription
src/coreclr/vm/prestub.cppAdds a per-method stripped-IL stub detection and throws a targeted BadImageFormatException.
src/coreclr/dlls/mscorrc/resource.hIntroduces BFA_STRIPPED_IL_BODY resource identifier.
src/coreclr/dlls/mscorrc/mscorrc.rcAdds the new error message string for BFA_STRIPPED_IL_BODY.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 1

Comment threadsrc/coreclr/vm/prestub.cpp
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 09:35
@kotlarmiloskotlarmilos added this to the 11.0.0 milestone Jun 30, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment threadsrc/coreclr/vm/prestub.cpp Outdated
Emit an intentionally invalid IL sentinel (illegal two-byte opcode
0xFE 0x24) for stripped method bodies instead of 'ldnull; throw', and
match that exact sentinel in the runtime. The previous stub collided
with a real 'throw null;' method body, which could trigger a false
BadImageFormatException if such a method ever needed to be JITted.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 12:44
kotlarmilosand others added 2 commits June 30, 2026 14:50
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp Outdated
CopilotAI review requested due to automatic review settings June 30, 2026 12:53

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
Comment threadsrc/coreclr/dlls/mscorrc/mscorrc.rc Outdated
…eedback
- prestub.cpp: EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE instead of throw;
named sentinel constants; comment covers JIT and interpreter
- Remove now-unused BFA_STRIPPED_IL_BODY resource
- CopiedMethodILNode: clarify sentinel comment
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 2, 2026 08:38
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
CopilotAI review requested due to automatic review settings July 2, 2026 08:46

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
kotlarmilos added a commit that referenced this pull request Jul 2, 2026
## Description
The `--strip-il-bodies` optimization in crossgen2 is applied when
building the composite ReadyToRun images that ship in the Apple mobile
runtime packs, and in #129813 it regressed by stripping the IL of
non-async `Task`/`ValueTask`-returning methods. That IL is still needed,
because with runtime-async enabled the runtime compiles a runtime-async
variant of such a method from its IL, so replacing it with a `ldnull`
throw stub threw `NullReferenceException` on the mobile packs until
#129884 narrowed the pass via `MayNeedILAtRuntime`.
This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that
inspect the emitted component MSIL to assert every branch of the strip
logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning
methods, a generic method, and a method on a generic type keep their IL,
while plain methods and async `Task<T>`/`ValueTask` methods are still
stripped.
TODO: This PR should be aligned with
#130025
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kotlarmilosand others added 2 commits July 2, 2026 15:28
… 0x24 stub
PR dotnet#130025 changes the crossgen2 --strip-il-bodies stub from ldnull; throw
(0x14 0x7A) to an invalid opcode (0xFE 0x24). Update the regression test
added in PR dotnet#130075 to check for the new sentinel bytes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kotlarmilos
kotlarmilos merged commit 6585d1c into dotnet:mainJul 3, 2026
111 checks passed
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
## Description
The `--strip-il-bodies` optimization in crossgen2 is applied when
building the composite ReadyToRun images that ship in the Apple mobile
runtime packs, and in #129813 it regressed by stripping the IL of
non-async `Task`/`ValueTask`-returning methods. That IL is still needed,
because with runtime-async enabled the runtime compiles a runtime-async
variant of such a method from its IL, so replacing it with a `ldnull`
throw stub threw `NullReferenceException` on the mobile packs until
#129884 narrowed the pass via `MayNeedILAtRuntime`.
This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that
inspect the emitted component MSIL to assert every branch of the strip
logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning
methods, a generic method, and a method on a generic type keep their IL,
while plain methods and async `Task<T>`/`ValueTask` methods are still
stripped.
TODO: This PR should be aligned with
#130025
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
…t runtime (#130025)
## Description
When crossgen2 is run with --strip-il-bodies, method bodies that were
precompiled and are not expected to be needed at runtime are replaced
with a minimal "ldnull; throw" stub. On a runtime without a JIT
fallback, if such a method is unexpectedly compiled at runtime the stub
surfaces as an opaque NullReferenceException, which gives no indication
that the real cause is a stripped IL body. This change detects the stub
on the per-method compile path and throws a descriptive error instead,
so the failure points at the actual problem. It complements the existing
image-level guards: the load-time rejection of stripped images on a JIT
runtime in readytoruninfo.cpp, and the eager-fixup fail-fast in
ceeload.cpp that fires when a failed fixup disables all ReadyToRun code.
Those guards cover whole-image configurations, while this one covers a
single method that is lazily compiled while ReadyToRun is otherwise
live, which is the case behind #129813.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@kotlarmilos@BrzVlad@jakobbotsch
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

[ios-clr] Throw descriptive error when a stripped IL body is needed at runtime - #130025

Merged
kotlarmilos merged 11 commits into
dotnet:mainfrom
kotlarmilos:dev/stripped-il-error-handling
Jul 3, 2026
Merged

[ios-clr] Throw descriptive error when a stripped IL body is needed at runtime#130025
kotlarmilos merged 11 commits into
dotnet:mainfrom
kotlarmilos:dev/stripped-il-error-handling

Conversation

@kotlarmilos

@kotlarmiloskotlarmilos commented Jun 30, 2026

Copy link
Copy Markdown
Member

Description

When crossgen2 is run with --strip-il-bodies, method bodies that were precompiled and are not expected to be needed at runtime are replaced with a minimal "ldnull; throw" stub. On a runtime without a JIT fallback, if such a method is unexpectedly compiled at runtime the stub surfaces as an opaque NullReferenceException, which gives no indication that the real cause is a stripped IL body. This change detects the stub on the per-method compile path and throws a descriptive error instead, so the failure points at the actual problem. It complements the existing image-level guards: the load-time rejection of stripped images on a JIT runtime in readytoruninfo.cpp, and the eager-fixup fail-fast in ceeload.cpp that fires when a failed fixup disables all ReadyToRun code. Those guards cover whole-image configurations, while this one covers a single method that is lazily compiled while ReadyToRun is otherwise live, which is the case behind #129813.

…t runtime
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves diagnostics for ReadyToRun images produced with --strip-il-bodies by detecting the minimal “stripped IL” stub at per-method compile time and throwing a descriptive BadImageFormatException instead of surfacing an opaque NullReferenceException from executing ldnull; throw.

Changes:

  • Detect the stripped-IL stub (ldnull; throw) during metadata IL header decode for ReadyToRun modules with stripped IL bodies and throw COR_E_BADIMAGEFORMAT with a dedicated BFA message.
  • Add a new BFA_STRIPPED_IL_BODY resource ID and corresponding user-facing error string.
Show a summary per file
FileDescription
src/coreclr/vm/prestub.cppAdds a per-method stripped-IL stub detection and throws a targeted BadImageFormatException.
src/coreclr/dlls/mscorrc/resource.hIntroduces BFA_STRIPPED_IL_BODY resource identifier.
src/coreclr/dlls/mscorrc/mscorrc.rcAdds the new error message string for BFA_STRIPPED_IL_BODY.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 1

Comment threadsrc/coreclr/vm/prestub.cpp
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 09:35
@kotlarmiloskotlarmilos added this to the 11.0.0 milestone Jun 30, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment threadsrc/coreclr/vm/prestub.cpp Outdated
Emit an intentionally invalid IL sentinel (illegal two-byte opcode
0xFE 0x24) for stripped method bodies instead of 'ldnull; throw', and
match that exact sentinel in the runtime. The previous stub collided
with a real 'throw null;' method body, which could trigger a false
BadImageFormatException if such a method ever needed to be JITted.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 30, 2026 12:44
kotlarmilosand others added 2 commits June 30, 2026 14:50
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp Outdated
CopilotAI review requested due to automatic review settings June 30, 2026 12:53

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
Comment threadsrc/coreclr/dlls/mscorrc/mscorrc.rc Outdated
…eedback
- prestub.cpp: EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE instead of throw;
named sentinel constants; comment covers JIT and interpreter
- Remove now-unused BFA_STRIPPED_IL_BODY resource
- CopiedMethodILNode: clarify sentinel comment
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 2, 2026 08:38
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
CopilotAI review requested due to automatic review settings July 2, 2026 08:46

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment threadsrc/coreclr/vm/prestub.cpp
kotlarmilos added a commit that referenced this pull request Jul 2, 2026
## Description
The `--strip-il-bodies` optimization in crossgen2 is applied when
building the composite ReadyToRun images that ship in the Apple mobile
runtime packs, and in #129813 it regressed by stripping the IL of
non-async `Task`/`ValueTask`-returning methods. That IL is still needed,
because with runtime-async enabled the runtime compiles a runtime-async
variant of such a method from its IL, so replacing it with a `ldnull`
throw stub threw `NullReferenceException` on the mobile packs until
#129884 narrowed the pass via `MayNeedILAtRuntime`.
This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that
inspect the emitted component MSIL to assert every branch of the strip
logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning
methods, a generic method, and a method on a generic type keep their IL,
while plain methods and async `Task<T>`/`ValueTask` methods are still
stripped.
TODO: This PR should be aligned with
#130025
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kotlarmilosand others added 2 commits July 2, 2026 15:28
… 0x24 stub
PR dotnet#130025 changes the crossgen2 --strip-il-bodies stub from ldnull; throw
(0x14 0x7A) to an invalid opcode (0xFE 0x24). Update the regression test
added in PR dotnet#130075 to check for the new sentinel bytes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kotlarmilos
kotlarmilos merged commit 6585d1c into dotnet:mainJul 3, 2026
111 checks passed
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
## Description
The `--strip-il-bodies` optimization in crossgen2 is applied when
building the composite ReadyToRun images that ship in the Apple mobile
runtime packs, and in #129813 it regressed by stripping the IL of
non-async `Task`/`ValueTask`-returning methods. That IL is still needed,
because with runtime-async enabled the runtime compiles a runtime-async
variant of such a method from its IL, so replacing it with a `ldnull`
throw stub threw `NullReferenceException` on the mobile packs until
#129884 narrowed the pass via `MayNeedILAtRuntime`.
This PR adds a deterministic `ILCompiler.ReadyToRun.Tests` tests that
inspect the emitted component MSIL to assert every branch of the strip
logic. Non-async `Task<T>`/`ValueTask<T>`/`Task`/`ValueTask`-returning
methods, a generic method, and a method on a generic type keep their IL,
while plain methods and async `Task<T>`/`ValueTask` methods are still
stripped.
TODO: This PR should be aligned with
#130025
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
…t runtime (#130025)
## Description
When crossgen2 is run with --strip-il-bodies, method bodies that were
precompiled and are not expected to be needed at runtime are replaced
with a minimal "ldnull; throw" stub. On a runtime without a JIT
fallback, if such a method is unexpectedly compiled at runtime the stub
surfaces as an opaque NullReferenceException, which gives no indication
that the real cause is a stripped IL body. This change detects the stub
on the per-method compile path and throws a descriptive error instead,
so the failure points at the actual problem. It complements the existing
image-level guards: the load-time rejection of stripped images on a JIT
runtime in readytoruninfo.cpp, and the eager-fixup fail-fast in
ceeload.cpp that fires when a failed fixup disables all ReadyToRun code.
Those guards cover whole-image configurations, while this one covers a
single method that is lazily compiled while ReadyToRun is otherwise
live, which is the case behind #129813.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 4, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@kotlarmilos@BrzVlad@jakobbotsch