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
CallSite with "platformapi" calling convention #145
Comments
We could certainly add it to the API, in the meantime you can simply pass 0x0100 and cast it to MethodCallingConvetion :) |
The values don't appear to match (e.g. MethodCallingConvention.C is 0x1 in Cecil, but is defined as 0x0200 in the spec.) If it's just a matter of finding where the corresponding byte is emitted, I could probably cook up a patch. Edit: huh, that's weird, this value appears to be written out as-is in AssemblyWriter.WriteMethodSignature(). I may be misinterpreting something in the spec: it says that these values are specific to pinvokeimpl (but SRE allows you to emit "winapi" which appears to work identically to "platformapi" for calli callsites.) Any ideas? |
Ah I see. You're mixing the pinvoke attributes and the byte flags used for the calling convention in a method signature. For the method signature, they're read in straight from the byte array: https://github.com/jbevain/cecil/blob/master/Mono.Cecil/AssemblyReader.cs#L2860 and written as is: https://github.com/jbevain/cecil/blob/master/Mono.Cecil/AssemblyWriter.cs#L2019 For the pinvoke attributes they're in: https://github.com/jbevain/cecil/blob/master/Mono.Cecil/PInvokeAttributes.cs And serialized properly as well. |
Aha, makes sense. In that case, what does SRE EmitCalli do? The documentation explicitly lists Winapi as supported, and it appears to work when you use it both on .Net and Mono. Edit (link markup failure): |
In mono it ends up doing: https://github.com/mono/mono/blob/master/mono/metadata/reflection.c#L3243 So the calling convention byte is set to the unmanaged calling convention minus one. WinAPI is 1, so I guess passing a zero value should do the trick, which is convenient as it's MethodCallingConvention.Default :) |
If I pass MethodCallingConvention.Default, then I get runtime failures on .Net/Windows. This affects mainly string/StringBuilder parameters (I marshal everything else myself), so I guess Default does not indicate that the callsite is unmanaged and the runtime does not generate the necessary unmanaged thunking code. Is there any way to verify whether a callsite is unmanaged? (If I open the binary in Xamarin Studio I do not see any mention of "unmanaged" in the dissassembly.) Edit: this is for an open-source projects btw (OpenTK) Edit 2: If I use MethodCallingConvention.StdCall, everything appears to be more or less working on .Net/Windows, so there's definitely something fishy going on with Default. |
It should be pretty easy to see what's going on with ildasm. In ILDASM you can set the Show Bytes option. So you can get the token of the signature that is passed to calli. Then you can do CTRL+M in ildasm, browse to the signatures (the easiest way is to search for Signature #1), and compare what is emitted by SRE with what's emitted with Cecil. |
Ok, just tried that. Results below. System.Reflection.Emit
CallingConvention.Winapi gives "unmanaged stdcall"! Same thing on Mono / Windows:
Mono / Windows gives managed call (probably a bug in the SRE implementation of Mono.) Next up is Mono.Cecil on .Net / Windows:
MethodCallingConvention.Default gives a regular managed call. If I switch Cecil to MethodCallingConvention.Stdcall, I get:
which is the same result as SRE on .Net / Windows. Phew, so it appears that SRE "Winapi" is interpreted as an alias to "Stdcall" and what happens next is up to the runtime. No magic after all and there really isn't anything to do in Cecil (other than possibly adding MethodCallingConvention.Winapi as an alias to Stdcall.) Thank you for your time! |
🙇 |
jbevain#145) * Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20240109.3 Microsoft.SourceBuild.Intermediate.source-build-reference-packages From Version 9.0.0-alpha.1.23627.2 -> To Version 9.0.0-alpha.1.24059.3 * Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20240117.1 Microsoft.SourceBuild.Intermediate.source-build-reference-packages From Version 9.0.0-alpha.1.23627.2 -> To Version 9.0.0-alpha.1.24067.1 * Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20240125.1 Microsoft.SourceBuild.Intermediate.source-build-reference-packages From Version 9.0.0-alpha.1.23627.2 -> To Version 9.0.0-alpha.1.24075.1 --------- Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com> Co-authored-by: Marek Safar <marek.safar@gmail.com>
According to the ECMA-335 spec, page 252, there exists a calling convention called "Platformapi" with a value of 0x0100. According to the description on page 188, the runtime translates this to an appropriate calling convention for the underlying platform (typically stdcall on Windows and cdecl on other platforms.)
When using System.Reflection.Emit, you can emit calli with an unmanaged callsite using the platformapi calling convention:
However, when trying to emit a calli through Cecil, there is no way to specify the platformapi convention (see MethodCallingConvention).
Is there some other way to construct a platformapi callsite? If not, would it be possible to add this to Cecil?
The text was updated successfully, but these errors were encountered: