Skip to content

Implement System.Runtime.CompilerServices.DisabledRuntimeMarshallingAttribute on CoreCLR-family of runtimes/type systems#63320

Merged
jkoritzinsky merged 64 commits into
dotnet:mainfrom
jkoritzinsky:disableruntimemarshalling
Jan 21, 2022
Merged

Implement System.Runtime.CompilerServices.DisabledRuntimeMarshallingAttribute on CoreCLR-family of runtimes/type systems#63320
jkoritzinsky merged 64 commits into
dotnet:mainfrom
jkoritzinsky:disableruntimemarshalling

Conversation

@jkoritzinsky

@jkoritzinsky jkoritzinsky commented Jan 4, 2022

Copy link
Copy Markdown
Member

Implement support for the new System.Runtime.CompilerServices.DisabledRuntimeMarshallingAttribute in the CoreCLR, R2R, and NativeAOT type systems/runtimes.

This feature (as discussed in API review), disables all runtime marshalling for P/Invokes, interop delegate types, and function pointer invocations defined within the assembly where the attribute is applied.

This also disables usage of SetLastError=true, PreserveSig=false and LCIDConversionAttribute on P/Invokes. Usage of any of these settings while using [assembly:DisabledRuntimeMarshalling] will result in a MarshalDirectiveException.

This PR also has a few minor fixes for NativeAOT:

  1. Bump the R2R version of NativeAOT to 6. This was missed in Change all "unmanaged" (no GC fields) sequential types to have sequential layout. #61759 as NativeAOT wasn't merged into dotnet/runtime yet.
  2. Change NativeAOT to throw a MarshalDirectiveException instead of a System.Exception when a parameter/field/return-value that cannot be marshalled is encountered to be consistent with CoreCLR.

This PR includes basic support in Mono. Further integration with Mono's componentization is tracked in #61685.

Fixes #60639

@ghost

ghost commented Jan 4, 2022

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@jkoritzinsky

jkoritzinsky commented Jan 4, 2022

Copy link
Copy Markdown
Member Author

I had a few open questions for reviewers:

  • Do we want to support CLR-integrated varargs (__arglist) when DisableRuntimeMarshallingAttribute is applied?

As there is no current alternative for varargs support today, I wanted to raise the question so we can decide whether or not we need to explicitly block it.

  • Do we want to support marshalling System.ArgIterator to the C va_list when DisableRuntimeMarshallingAttribute is applied?

Since va_list is a platform-specific type that has different layouts on each platform, it's not really practical for developers to provide their own implementations; however, we are also planning on moving away from the CLR-integrated varargs support, so I don't know if we want to explicitly enable support for System.ArgIterator when the attribute is applied.

  • When DisableRuntimeMarshallingAttribute is applied, we aren't blocking unmanaged value types that explicitly have auto-layout. Right now, we're supporting passing them as-is but with unspecified behavior (as the layout itself is unspecified). Do we want to block value types that have LayoutKind.Auto members in P/Invokes when DisableRuntimeMarshallingAttribute is applied?

@stephentoub

Copy link
Copy Markdown
Member

Fixes #60639

Is the plan to eventually apply this on all of our assemblies produced from dotnet/runtime? If so, is that tracked separately?

@jkoritzinsky

Copy link
Copy Markdown
Member Author

As we will be updating the spec for user-defined value type marshalling with DllImportGenerator to require this attribute, we will update the assemblies defined in dotnet/runtime to have this attribute applied as part of that change.

@AaronRobinsonMSFT AaronRobinsonMSFT left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great start. Now that we are moving toward reconciling blittable and unmanaged, we should also update the BOTR.

@AaronRobinsonMSFT

Copy link
Copy Markdown
Member

Do we want to support CLR-integrated varargs (__arglist) when DisableRuntimeMarshallingAttribute is applied?

Great question. I consider it part of the marshalling logic. I think it should apply. I would however like to see how C++/CLI plays with this attribute. I'm not sure how far one would get with C++/CLI if it were applied in general.

Do we want to support marshalling System.ArgIterator to the C va_list when DisableRuntimeMarshallingAttribute is applied?

I'd prefer this to be disabled.

When DisableRuntimeMarshallingAttribute is applied, we aren't blocking unmanaged value types that explicitly have auto-layout. Right now, we're supporting passing them as-is but with unspecified behavior (as the layout itself is unspecified). Do we want to block value types that have LayoutKind.Auto members in P/Invokes when DisableRuntimeMarshallingAttribute is applied?

I think disabling this is appropriate.

Comment thread src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs Outdated
Comment thread src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs Outdated
Comment thread src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs Outdated

private MethodIL EmitIL()
{
if (_targetMethod.HasCustomAttribute("System.Runtime.InteropServices", "LCIDConversionAttribute"))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs
Comment thread src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs Outdated
Comment thread src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs Outdated
Comment thread src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs Outdated
Comment thread src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs Outdated
Comment thread src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs Outdated
Comment thread src/coreclr/vm/mlinfo.cpp
@marek-safar

Copy link
Copy Markdown
Contributor

This also disables usage of SetLastError=true, PreserveSig=false and LCIDConversionAttribute on P/Invokes. Usage of any of these settings while using [assembly:DisabledRuntimeMarshalling] will result in a MarshalDirectiveException.

Will the analyzer be available for a better developer experience?

@lambdageek

Copy link
Copy Markdown
Member

This PR does not include Mono support. That is tracked in #61685.

@jkoritzinsky Could you add the new tests to issues.targets to disable them on Mono for now.

@elinor-fung elinor-fung left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be pro blocking/disabling ArgIterator/varargs/auto-layout when runtime marshalling is disabled.

Comment thread src/coreclr/dlls/mscorrc/mscorrc.rc Outdated

@MichalStrehovsky MichalStrehovsky left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Crossgen2/NativeAOT changes look good! Thank you!

Comment thread src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs Outdated
Comment thread src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs Outdated
Comment thread src/coreclr/dlls/mscorrc/mscorrc.rc Outdated
Comment thread src/mono/mono/metadata/marshal.c Outdated

if (m_type_is_byref(t)) {
if (emit_exception)
get_marshal_cb ()->emit_marshal_directive_exception (m, argnum, "Cannot marshal managed references when the built-in marshalling system is disabled.");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should such error messages include the assembly name?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the P/Invoke method will be included in the stack trace, I don't think we need to include the assembly name here.

@marek-safar

Copy link
Copy Markdown
Contributor

@vargaz could you review mono changes?

Comment thread src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs
Comment thread src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs Outdated
/// - LCIDConversionAttribute support is disabled.
/// </remarks>
[AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)]
public sealed class DisableRuntimeMarshallingAttribute : Attribute

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tried to mark CoreLib with this and see what breaks? Should we add it to CoreLib as part to this PR?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't tried applying this attribute to CoreLib yet. It looks like we have a few regular DllImports that are waiting on the next phase of work after this attribute gets in (described in #63765) to handle cases where we pass System.Guids to and from native code. Once we put this PR in, we can update the DllImportGenerator based on #63765, convert the rest of the DllImports over to the generated ones, and apply this attribute.

I might throw up another PR next week based on this one that applies the attribute just to see all that breaks.

Comment thread src/coreclr/vm/classlayoutinfo.cpp Outdated
Comment thread src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs Outdated

@jkotas jkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@jkoritzinsky jkoritzinsky added the blocking Marks issues that we want to fast track in order to unblock other important work label Jan 18, 2022
@jkoritzinsky

Copy link
Copy Markdown
Member Author

Marking as blocking as a lot of the planned work for the Interop team (the rest of DllImportGenerator productization) requires this PR.

Comment thread src/coreclr/dlls/mscorrc/mscorrc.rc Outdated
Comment thread src/tests/Common/tests.targets
Comment thread src/coreclr/vm/classlayoutinfo.cpp
using System.Runtime.InteropServices;
using Xunit;

public unsafe class DisabledRuntimeMarshallingNative

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For after this PR: thoughts on pulling out the common parts between this and the one under Native_Default or having one file with ifdefs?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe... Depends on how much would actually be common between the two.

Comment thread src/coreclr/vm/mlinfo.cpp Outdated
Comment thread src/coreclr/vm/mlinfo.cpp
@vargaz

vargaz commented Jan 20, 2022

Copy link
Copy Markdown
Contributor

The mono changes look ok, it could use a bit of cleanup later but nothing that would hold up this PR imho.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-Interop-coreclr blocking Marks issues that we want to fast track in order to unblock other important work new-api-needs-documentation