How to tell if a function is managed code?
This is a moot point for pure C# apps, but what if you're writing in MC++ (or some other 'mixed' language) and you want to know if a function is getting compiled as managed or native code?
You can try and inspect the source and infer from the language rules. Eg, in MC++, look for #pragma managed / #pragma unmanaged. However, that's risky because maybe there's some language rule that you're not aware of. (Pop quiz: Do you know all the rules that will cause MC++ to compile a function into native code instead of IL?)
So if you want more paranoid verification...
- Use ILDasm to see if the function is actually IL.
- If it shows up while managed-only debugging, then it's managed code. So check if you're interop debugging, and if you're not, anything you see is managed.
- Look for Managed-2-Native markers on the callstack.
- If you're actually stopped in the function while debugging, view the disassembly.
VS shows managed debugging disassembly starting with offset 0, eg:
int main(array<System::String ^> ^args) { Console::WriteLine(L"Hello World"); 00000000 push edi 00000001 push esi 00000002 push ebx
Whereas native disassembly is shown with absolute addresses:
int Add(int a, int b) { 00401000 push ebp 00401001 mov ebp,esp return a + b; 00401003 mov eax,dword ptr [a] 00401006 add eax,dword ptr [b] }
This is clearly a heuristic since it's just a behavior-specific aspect of VS. The CLR Debugging services provides the actual address of jitted code, so VS could show both manage and native disassembly the same. However, the stackwalking APIs are 100% clear about whether code is managed or native, so a debugger tool can also pass that information onto the user.
Comments
- Anonymous
October 12, 2007
Alternatively, if you know that the code has not been ngen'd, you can examine the virtual address of the first instruction. In your first sample, the address will not be located in any loaded module, but in memory that has been allocated by the JIT compiler (presumably this is why VS shows a zero offset since the address could possibly change with a later re-JIT). In the latter sample, the virtual address will be found inside the module's range probably in the .text section. If the code has been ngen'd, you might then be able to fall back on the heuristics you give.