Skip to content

[interp] DynamicMethod with a CALL of a P/Invoke throws "BadImageFormatException: Method has no body" #38897

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
lambdageek opened this issue Jul 7, 2020 · 4 comments · Fixed by #40266 or mono/mono#20199
Assignees
Labels

Comments

@lambdageek
Copy link
Member

Description

The following program correctly calls the P/Invoke when runnign with the JIT, but throws a BadImageFormatException: Method has no body under the interpreter.

using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;


namespace HelloWorld
{
	public delegate void NativeMethodInvoker ();

	class Program
	{
		static void Main(string[] args)
		{
			Test1 ();
		}

		public static void Test1 ()
		{
			Console.WriteLine($"Running {nameof(Test1)}...");

			DynamicMethod testUnmanagedCallersOnly = new DynamicMethod("UnmanagedCallersOnly", null, null, typeof(Program).Module);
			ILGenerator il = testUnmanagedCallersOnly.GetILGenerator();
			il.Emit(OpCodes.Nop);
		    
			il.Emit (OpCodes.Ldc_I4_0);
			il.Emit (OpCodes.Conv_I);

			il.Emit(OpCodes.Call, typeof(Program).GetMethod(nameof (CallThing)));
			il.Emit(OpCodes.Nop);
			il.Emit(OpCodes.Ret);
			var testNativeMethod = (NativeMethodInvoker)testUnmanagedCallersOnly.CreateDelegate(typeof(NativeMethodInvoker));

			testNativeMethod ();
		}

		[DllImport ("Foo", EntryPoint="call_thing")]
		public static extern void CallThing (IntPtr pFn);
	}
}

and clang -o libFoo.dylib -shared foo.c where foo.c is:

#include <stdio.h>

void
call_thing (void *p)
{
	printf ("in call_thing %p\n", p);
}

Configuration

Mono on OSX. Both net5 and mono/mono master.

Regression?

not sure

Other information

Expected output:

Running Test1...
in call_thing 0x0

Actual output:

Running Test1...

Unhandled Exception:
System.BadImageFormatException: Method has no body
File name: 'Program'
  at (wrapper dynamic-method) System.Object.UnmanagedCallersOnly()
  at (wrapper delegate-invoke) <Module>.invoke_void()
  at HelloWorld.Program.Test1 () <0x7ff17605d808 + 0x00124> in <2250f8cc19ca4afc839a8fabb2d1d0b4>:0
  at HelloWorld.Program.Main (System.String[] args) <0x7ff17700c170 + 0x00000> in <2250f8cc19ca4afc839a8fabb2d1d0b4>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.BadImageFormatException: Method has no body
File name: 'Program'
  at (wrapper dynamic-method) System.Object.UnmanagedCallersOnly()
  at (wrapper delegate-invoke) <Module>.invoke_void()
  at HelloWorld.Program.Test1 () <0x7ff17605d808 + 0x00124> in <2250f8cc19ca4afc839a8fabb2d1d0b4>:0
  at HelloWorld.Program.Main (System.String[] args) <0x7ff17700c170 + 0x00000> in <2250f8cc19ca4afc839a8fabb2d1d0b4>:0
@ghost
Copy link

ghost commented Jul 7, 2020

Tagging subscribers to this area: @BrzVlad, @lewurm
Notify danmosemsft if you want to be subscribed.

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the untriaged New issue has not been triaged by the area owner label Jul 7, 2020
@lambdageek
Copy link
Member Author

Just calling the method directly, without reflection using CallThing (IntPtr.Zero) works as expected with the interpreter. The IL should be the same, AFAICT...

@fanyang-mono fanyang-mono self-assigned this Jul 14, 2020
@fanyang-mono fanyang-mono removed the untriaged New issue has not been triaged by the area owner label Aug 1, 2020
@fanyang-mono
Copy link
Member

fanyang-mono commented Aug 3, 2020

This is the stack trace which triggered this exception:

frame #0: 0x0000000102b392d8 libcoreclr.dylib`mono_method_has_no_body(method=0x00000001008fd248) at loader.c:2014:11
frame #1: 0x0000000102b393ba libcoreclr.dylib`mono_method_get_header_internal(method=0x00000001008fd248, error=0x00007ffeefbfc038) at loader.c:2039:6
frame #2: 0x0000000102b396a7 libcoreclr.dylib`mono_method_get_header_checked(method=0x00000001008fd248, error=0x00007ffeefbfc038) at loader.c:2102:9
frame #3: 0x0000000102a5e8b0 libcoreclr.dylib`mono_interp_transform_method(imethod=0x000000010208e8d8, context=0x000000010021ed80, error=0x00007ffeefbfc038) at transform.c:8075:12
frame #4: 0x0000000102a445d9 libcoreclr.dylib`do_transform_method(frame=0x00007ffeefbfc9e0, context=0x000000010021ed80) at interp.c:2526:2
frame #5: 0x0000000102a287d0 libcoreclr.dylib`interp_exec_method at interp.c:3365:23
frame #6: 0x0000000102a28775 libcoreclr.dylib`interp_exec_method(frame=0x00007ffeefbfc9e0, context=0x000000010021ed80, clause_args=0x0000000000000000) at interp.c:3983
frame #7: 0x0000000102a24a3f libcoreclr.dylib`interp_runtime_invoke(method=0x000000010061e658, obj=0x0000000000000000, params=0x00007ffeefbfec10, exc=0x0000000000000000, error=0x00007ffeefbfecd8) at interp.c:1911:2
frame #8: 0x000000010281650a libcoreclr.dylib`mono_jit_runtime_invoke(method=0x000000010061e658, obj=0x0000000000000000, params=0x00007ffeefbfec10, exc=0x0000000000000000, error=0x00007ffeefbfecd8) at mini-runtime.c:3197:10
frame #9: 0x0000000102b8a7aa libcoreclr.dylib`do_runtime_invoke(method=0x000000010061e658, obj=0x0000000000000000, params=0x00007ffeefbfec10, exc=0x0000000000000000, error=0x00007ffeefbfecd8) at object.c:3045:11
frame #10: 0x0000000102b84d11 libcoreclr.dylib`mono_runtime_invoke_checked(method=0x000000010061e658, obj=0x0000000000000000, params=0x00007ffeefbfec10, error=0x00007ffeefbfecd8) at object.c:3213:9
frame #11: 0x0000000102b8fd75 libcoreclr.dylib`do_exec_main_checked(method=0x000000010061e658, args=0x0000000103801438, error=0x00007ffeefbfecd8) at object.c:5281:3
frame #12: 0x0000000102b8e033 libcoreclr.dylib`mono_runtime_exec_main_checked(method=0x000000010061e658, args=0x0000000103801438, error=0x00007ffeefbfecd8) at object.c:5378:9
frame #13: 0x0000000102b8e086 libcoreclr.dylib`mono_runtime_run_main_checked(method=0x000000010061e658, argc=1, argv=0x0000000100707dc0, error=0x00007ffeefbfecd8) at object.c:4728:9
frame #14: 0x00000001028c7060 libcoreclr.dylib`mono_jit_exec_internal(domain=0x000000010030c820, assembly=0x000000010023a460, argc=1, argv=0x0000000100707dc0) at driver.c:1391:13
frame #15: 0x00000001028c6e6d libcoreclr.dylib`mono_jit_exec(domain=0x000000010030c820, assembly=0x000000010023a460, argc=1, argv=0x0000000100707dc0) at driver.c:1336:7
frame #16: 0x00000001028cbc91 libcoreclr.dylib`main_thread_handler(user_data=0x00007ffeefbff160) at driver.c:1473:3
frame #17: 0x00000001028ca07f libcoreclr.dylib`mono_main(argc=3, argv=0x0000000100707db0) at driver.c:2754:3

However, il.Emit(OpCodes.Call, typeof(Program).GetMethod(nameof (CallThing))); should cause the interpreter to call the native CallThing function.

@fanyang-mono
Copy link
Member

This is where the bug was

frame #0: 0x0000000102a6d78f libcoreclr.dylib`interp_transform_internal_calls(method=0x0000000100434020, target_method=0x000000010182fa48, csignature=0x000000010182faa8, is_virtual=0) at transform.c:1905:18
frame #1: 0x0000000102a66776 libcoreclr.dylib`interp_transform_call(td=0x00007ffeefbfb838, method=0x0000000100434020, target_method=0x000000010182fa48, domain=0x000000010021a030, generic_context=0x0000000000000000, is_bb_start="\x01", constrained_class=0x0000000000000000, readonly=0, error=0x00007ffeefbfbf00, check_visibility=1, save_last_error=0) at transform.c:2435:18
frame #2: 0x0000000102a4d9d5 libcoreclr.dylib`generate_code(td=0x00007ffeefbfb838, method=0x0000000100434020, header=0x0000000100434430, generic_context=0x0000000000000000, error=0x00007ffeefbfbf00) at transform.c:3915:9
frame #3: 0x0000000102a5f1d7 libcoreclr.dylib`generate(method=0x0000000100434020, header=0x0000000100434430, rtm=0x00007ffeefbfba30, generic_context=0x0000000000000000, error=0x00007ffeefbfbf00) at transform.c:7828:2
frame #4: 0x0000000102a5e991 libcoreclr.dylib`mono_interp_transform_method(imethod=0x00007ffeefbfba30, context=0x0000000100235610, error=0x00007ffeefbfbf00) at transform.c:8081:2
frame #5: 0x0000000102a24e44 libcoreclr.dylib`interp_init_delegate(del=0x000000010300a3c8, error=0x00007ffeefbfbf00) at interp.c:1634:3
frame #6: 0x000000010281643e libcoreclr.dylib`mini_init_delegate(delegate=MonoDelegateHandle @ 0x00007ffeefbfbc78, target=MonoObjectHandle @ 0x00007ffeefbfbc70, addr=0x0000000000000000, method=0x0000000100434020, error=0x00007ffeefbfbf00) at mini-runtime.c:3796:3
frame #7: 0x0000000102b97c77 libcoreclr.dylib`mono_delegate_ctor(this_obj=MonoObjectHandle @ 0x00007ffeefbfbd80, target=MonoObjectHandle @ 0x00007ffeefbfbd78, addr=0x0000000000000000, method=0x0000000100434020, error=0x00007ffeefbfbf00) at object.c:8854:2
frame #8: 0x0000000102b15f26 libcoreclr.dylib`ves_icall_System_Delegate_CreateDelegate_internal(ref_type=MonoReflectionTypeHandle @ 0x00007ffeefbfbe50, target=MonoObjectHandle @ 0x00007ffeefbfbe48, info=MonoReflectionMethodHandle @ 0x00007ffeefbfbe40, throwOnBindFailure='\x01', error=0x00007ffeefbfbf00) at icall.c:7349:2
frame #9: 0x0000000102b1af75 libcoreclr.dylib`ves_icall_System_Delegate_CreateDelegate_internal_raw(a0=0x0000000104959100, a1=0x0000000104959108, a2=0x0000000104959110, a3='\x01') at icall-def-netcore.h:62:1
frame #10: 0x0000000102a44a31 libcoreclr.dylib`do_icall(sig=0x00000001018758a0, op=577, sp=0x0000000104959128, ptr=0x0000000102b1aee0, save_last_error=0) at interp.c:2133:20
frame #11: 0x0000000102a41edc libcoreclr.dylib`do_icall_wrapper(frame=0x00007ffeefbfc8f0, sig=0x00000001018758a0, op=577, sp=0x0000000104959140, ptr=0x0000000102b1aee0, save_last_error=0) at interp.c:2189:7
frame #12: 0x0000000102a27c0f libcoreclr.dylib`interp_exec_method(frame=0x00007ffeefbfc8f0, context=0x0000000100235610, clause_args=0x0000000000000000) at interp.c:3781:9

fanyang-mono added a commit to mono/mono that referenced this issue Aug 4, 2020
Fixes dotnet/runtime#38897 , by allowing transforming internal calls when method is dynamic.

Co-authored-by: fanyang-mono <fanyang-mono@users.noreply.github.com>
@ghost ghost locked as resolved and limited conversation to collaborators Dec 8, 2020
# for free to subscribe to this conversation on GitHub. Already have an account? #.
Labels
Projects
None yet
3 participants