Skip to content

Conversation

janvorli
Copy link
Member

The ExecutionManager::GetCodeMethodDesc expects that the address passed to it is an address of actual JIT/AOT or interpreter generated code. However, it is sometimes passed an address of the interpreter precode, e.g. in the case when called by the
MethodTable::GetMethodDescForSlotAddress. The VTable slots need to point to the interpreter stub so that these methods can be called by virtual calls from native code.

This issue occurs in several methods on the .NET runtime startup path when running interpreted.

This change adds a check for the interpreter precode to the ExecutionManager::GetCodeMethodDesc and extracts the MethodDesc from the interpreter data in case it is passed the precode address.

The ExecutionManager::GetCodeMethodDesc expects that the address
passed to it is an address of actual JIT/AOT or interpreter generated
code. However, it is sometimes passed an address of the interpreter
precode, e.g. in the case when called by the
MethodTable::GetMethodDescForSlotAddress. The VTable slots need to point
to the interpreter stub so that these methods can be called by virtual
calls from native code.

This change adds a check for the interpreter precode to the
ExecutionManager::GetCodeMethodDesc and extracts the MethodDesc from the
interpreter data in case it is passed the precode address.
@janvorli janvorli added this to the 10.0.0 milestone Jul 14, 2025
@janvorli janvorli requested review from kg, jkotas and kotlarmilos July 14, 2025 20:51
@janvorli janvorli self-assigned this Jul 14, 2025
@Copilot Copilot AI review requested due to automatic review settings July 14, 2025 20:51
Copy link
Contributor

Tagging subscribers to this area: @BrzVlad, @janvorli, @kg
See info in area-owners.md if you want to be subscribed.

Copy link
Contributor

@Copilot Copilot AI left a comment

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 enhances the runtime’s handling of interpreter precodes by enabling ExecutionManager::GetCodeMethodDesc and Precode::GetMethodDesc to resolve a MethodDesc when given an interpreter precode entry point. Key changes include:

  • Added GetMethodDesc in InterpreterPrecode and wiring it into Precode::GetMethodDesc
  • Introduced Precode::AsInterpreterPrecode helper for casting to InterpreterPrecode
  • Updated ExecutionManager::GetCodeMethodDesc to detect interpreter precodes and return the associated MethodDesc

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/coreclr/vm/precode.h Declare InterpreterPrecode::GetMethodDesc, PTR_InterpreterPrecode, and AsInterpreterPrecode
src/coreclr/vm/precode.cpp Include interpreter header, implement InterpreterPrecode::GetMethodDesc, update Precode::GetMethodDesc
src/coreclr/vm/codeman.cpp Add interpreter-precode check in ExecutionManager::GetCodeMethodDesc
Comments suppressed due to low confidence (2)

src/coreclr/vm/precode.h:339

  • [nitpick] Consider adding a brief XML doc comment above GetMethodDesc() to explain that it returns the raw MethodDesc pointer stored in the interpreter precode data.
    TADDR GetMethodDesc();

src/coreclr/vm/codeman.cpp:5094

  • It would be helpful to add a unit or integration test that drives ExecutionManager::GetCodeMethodDesc with an interpreter precode address to ensure this new branch correctly returns the expected MethodDesc.
    PTR_Precode pPrecode = Precode::GetPrecodeFromEntryPoint(currentPC);

@jkotas
Copy link
Member

jkotas commented Jul 14, 2025

However, it is sometimes passed an address of the interpreter precode, e.g. in the case when called by the
MethodTable::GetMethodDescForSlotAddress

Would it be more appropriate for the fix to be in MethodTable::GetMethodDescForSlotAddress?

@jkotas
Copy link
Member

jkotas commented Jul 14, 2025

ExecutionManager::GetCodeMethodDesc is meant to be used on arbitrary IP in the middle of a method. I think it is fragile to depend on the asm code match in Precode::GetPrecodeFromEntryPoint to be able to reject code from arbitrary IPs.

@janvorli
Copy link
Member Author

ExecutionManager::GetCodeMethodDesc is meant to be used on arbitrary IP in the middle of a method.

Hmm, ok, I didn't know that. In that case, I'll move it to the MethodTable::GetMethodDescForSlotAddress. I have thought I've seen other caller ExecutionManager::GetCodeMethodDesc that could have the same problem, but checking it now, it was in the debugger code, so it is the known issue we have discussed some time ago and that I have a fix for locally.

@janvorli
Copy link
Member Author

@jkotas, ok, the funny part is that with the changes I've added in precode.cpp and precode.h to get MethodDesc for InterpreterPrecode, neither the MethodTable::GetMethodDescForSlotAddress nor ExecutionManager::GetCodeMethodDesc needs to be modified. The MethodTable::GetMethodDescForSlotAddress actually gets the MethodDesc from the precode as the last step if other ones don't work.

@janvorli
Copy link
Member Author

/ba-g the android build seems to be timing out on multiple CI runs

@janvorli janvorli merged commit b0f0088 into dotnet:main Jul 15, 2025
96 of 98 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators Aug 15, 2025
Sign up for free to 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.

2 participants