Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

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

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
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
3 participants