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

Initial Stable Id stuff #1

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft

Initial Stable Id stuff #1

wants to merge 1 commit into from

Conversation

dellis1972
Copy link
Owner

No description provided.

dellis1972 pushed a commit that referenced this pull request Apr 14, 2020
Context: https://github.com/jfversluis/SwipeViewDemo
Context: https://github.com/xamarin/Xamarin.Forms/blob/fa33ca3b3ac5c7c875023db785b56c67015e13b1/Xamarin.Forms.Platform.Android/AppCompat/TabbedPageRenderer.cs#L512

Commit 7117414 introduced native code which queries the Mono runtime
to obtain an instance of a `MonoClass` for a given `MonoReflectionType`
as well as the `MonoImage` associated with the `MonoClass`:

	// EmbeddedAssemblies::typemap_managed_to_java(MonoReflectionType *reflection_type, const uint8_t *mvid)
	MonoReflectionType     *reflection_type = …
	MonoType               *type            = mono_reflection_type_get_type (reflection_type);
	MonoClass              *klass           = mono_type_get_class (type);   // PROBLEMATIC
	// EmbeddedAssemblies::typemap_managed_to_java(MonoType *type, MonoClass *klass, const uint8_t *mvid)
	MonoImage              *image           = mono_class_get_image (klass);

However, it appears that when dealing with closed generic types -- such
as with `new GenericHolder<int>()` -- the above call chain results in a
SIGSEGV instead of a valid `MonoImage*`:

	F libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x3000021 in tid 19030 (s.swipeviewdemo), pid 19030 (s.swipeviewdemo)
	I crash_dump32: obtaining output fd from tombstoned, type: kDebuggerdTombstone
	I /system/bin/tombstoned: received crash request for pid 19030
	I crash_dump32: performing dump of process 19030 (target tid = 19030)
	F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
	F DEBUG   : Build fingerprint: 'google/sdk_gphone_x86/generic_x86:10/QSR1.191030.002/5978551:userdebug/dev-keys'
	F DEBUG   : Revision: '0'
	F DEBUG   : ABI: 'x86'
	F DEBUG   : Timestamp: 2020-04-08 15:52:55+0200
	F DEBUG   : pid: 19030, tid: 19030, name: s.swipeviewdemo  >>> nl.versluis.swipeviewdemo <<<
	F DEBUG   : uid: 10135
	F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x3000021
	F DEBUG   :     eax 03000005  ebx cb9f4d24  ecx 7191c13b  edx 00000004
	F DEBUG   :     edi 03000005  esi ffb22080
	F DEBUG   :     ebp ffb22108  esp ffb2206c  eip cbcfc1e4
	F DEBUG   :
	F DEBUG   : backtrace:
	F DEBUG   :       #00 pc 001b41e4  /data/app/Mono.Android.DebugRuntime-umHhDz421s4-tshrHwha0w==/lib/x86/libmonosgen-32bit-2.0.so (mono_image_get_name+4)
	F DEBUG   :       #1 pc 0000cac7  /data/app/nl.versluis.swipeviewdemo-jCFH_bcCNuFx1tLUhaJ4nw==/lib/x86/libmonodroid.so (xamarin::android::internal::EmbeddedAssemblies::typemap_managed_to_java(_MonoType*, _MonoClass*, unsigned char const*)+263) (BuildId: a2585ad379f788049e463af58c8686e9cdc1e778)
	F DEBUG   :       #2 pc 0000c8cc  /data/app/nl.versluis.swipeviewdemo-jCFH_bcCNuFx1tLUhaJ4nw==/lib/x86/libmonodroid.so (xamarin::android::internal::EmbeddedAssemblies::typemap_managed_to_java(_MonoReflectionType*, unsigned char const*)+124) (BuildId: a2585ad379f788049e463af58c8686e9cdc1e778)
	F DEBUG   :       #3 pc 0001621a  /data/app/nl.versluis.swipeviewdemo-jCFH_bcCNuFx1tLUhaJ4nw==/lib/x86/libmonodroid.so (xamarin::android::internal::MonodroidRuntime::typemap_managed_to_java(_MonoReflectionType*, unsigned char const*)+42) (BuildId: a2585ad379f788049e463af58c8686e9cdc1e778)
	F DEBUG   :       #4 pc 000325af  <anonymous:c7858000>

Investigating the issue I discovered that one of two things happened:

 1. the returned `MonoImage` instance was invalid, *or*
 2. the instance was valid but image name stored in `MonoImage`
    was `null`

(1) would only happen in 32-bit builds, resulting in a SIGSEGV within
`mono_image_get_name()`, because the `image` pointer value of 0x3000005
was invalid:

	I monodroid: const char *xamarin::android::internal::EmbeddedAssemblies::typemap_managed_to_java(MonoType *, MonoClass *, const uint8_t *)
	I monodroid:   type == 0xc6e60d3c, klass == 0xc6e60cb8, mvid == 0xc8c02d90
	I monodroid:   type name == Xamarin.Forms.Platform.Android.AppCompat.FormsFragmentPagerAdapter`1[Xamarin.Forms.Page]
	I monodroid:   calling mono_class_get_image (0xc6e60cb8)
	I monodroid:     image == 0x3000005

(2) only happened in 64-bit builds, resulting in a SIGSEGV as
`strlen()` was passed a `null` pointer:

	I monodroid: const char *xamarin::android::internal::EmbeddedAssemblies::typemap_managed_to_java(MonoType *, MonoClass *, const uint8_t *)
	I monodroid:   type == 0x7ce3fecc78, klass == 0x7ce3fecb98, mvid == 0x7ce9404520
	I monodroid:   type name == Xamarin.Forms.Platform.Android.AppCompat.FormsFragmentPagerAdapter`1[Xamarin.Forms.Page]
	I monodroid:   calling mono_class_get_image (0x7ce3fecb98)
	I monodroid:     image == 0x7ce3fecbc8
	I monodroid:     image_name == <null>

I found out that the root cause was in the `mono_type_get_class()` call
which is supposed to be used with great caution as it eventually calls
the `mono_type_get_class_internal()` function which is supposed to be
called only for object types `MONO_TYPE_CLASS` and `MONO_TYPE_VALUETYPE`
but not `MONO_TYPE_GENERICINST`, and `MONO_TYPE_GENERICINST` is used
for closed generic types.

The fix is to call the `mono_class_from_mono_type()` function instead
which, albeit slower, is safer and works correctly in all cases:

	// EmbeddedAssemblies::typemap_managed_to_java(MonoReflectionType *reflection_type, const uint8_t *mvid)
	MonoReflectionType     *reflection_type = …
	MonoType               *type            = mono_reflection_type_get_type (reflection_type);
	MonoClass              *klass           = mono_class_from_mono_type (type);     // PART OF THE FIX
	// EmbeddedAssemblies::typemap_managed_to_java(MonoType *type, MonoClass *klass, const uint8_t *mvid)
	MonoImage              *image           = mono_class_get_image (klass)

Fixing this led to the next issue, a managed exception thrown after the
runtime failed to map a managed type name to Java type name:

	W monodroid-assembly: typemap: unable to find mapping to a Java type from managed type 'Xamarin.Forms.Platform.Android.AppCompat.FormsFragmentPagerAdapter`1[T], Xamarin.Forms.Platform.Android'
	I monodroid-timing: Typemap.managed_to_java: end, total time; elapsed: 0s:0::33177
	D Mono    : DllImport attempting to load: '/system/lib64/liblog.so'.
	D Mono    : DllImport loaded library '/system/lib64/liblog.so'.
	D Mono    : DllImport searching in: '/system/lib64/liblog.so' ('/system/lib64/liblog.so').
	D Mono    : Searching for '__android_log_print'.
	D Mono    : Probing '__android_log_print'.
	D Mono    : Found as '__android_log_print'.
	I MonoDroid: UNHANDLED EXCEPTION:
	I MonoDroid: System.NotSupportedException: Cannot create instance of type 'Xamarin.Forms.Platform.Android.AppCompat.FormsFragmentPagerAdapter`1[[Xamarin.Forms.Page, Xamarin.Forms.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null]]': no Java peer type found.
	I MonoDroid:   at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x0004b] in <514e1249792e47a180b3f1293306b972>:0
	I MonoDroid:   at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <514e1249792e47a180b3f1293306b972>:0
	I MonoDroid:   at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <514e1249792e47a180b3f1293306b972>:0
	I MonoDroid:   at Android.Support.V4.App.FragmentPagerAdapter..ctor (Android.Support.V4.App.FragmentManager fm) [0x0005b] in <fefee6c2c695459088a9df092723e052>:0
	I MonoDroid:   at Xamarin.Forms.Platform.Android.AppCompat.FormsFragmentPagerAdapter`1[T]..ctor (Xamarin.Forms.MultiPage`1[T] page, Android.Support.V4.App.FragmentManager fragmentManager) [0x00000] in <9d12bb15abb54c508c4bee636d1b3a42>:0
	I MonoDroid:   at Xamarin.Forms.Platform.Android.AppCompat.TabbedPageRenderer.CreateFormsViewPager (Android.Content.Context context, Xamarin.Forms.TabbedPage tabbedPage) [0x00033] in <9d12bb15abb54c508c4bee636d1b3a42>:0
	I MonoDroid:   at Xamarin.Forms.Platform.Android.AppCompat.TabbedPageRenderer.OnElementChanged (Xamarin.Forms.Platform.Android.ElementChangedEventArgs`1[TElement] e) [0x001cd] in <9d12bb15abb54c508c4bee636d1b3a42>:0
	I MonoDroid:   at Xamarin.Forms.Platform.Android.VisualElementRenderer`1[TElement].SetElement (TElement element) [0x000c0] in <9d12bb15abb54c508c4bee636d1b3a42>:0
	I MonoDroid:   at Xamarin.Forms.Platform.Android.VisualElementRenderer`1[TElement].Xamarin.Forms.Platform.Android.IVisualElementRenderer.SetElement (Xamarin.Forms.VisualElement element) [0x00033] in <9d12bb15abb54c508c4bee636d1b3a42>:0
	I MonoDroid:   at Xamarin.Forms.Platform.Android.Platform.CreateRenderer (Xamarin.Forms.VisualElement element, Android.Content.Context context) [0x0001f] in <9d12bb15abb54c508c4bee636d1b3a42>:0
	I MonoDroid:   at Xamarin.Forms.Platform.Android.AppCompat.Platform.AddChild (Xamarin.Forms.Page page, System.Boolean layout) [0x0000d] in <9d12bb15abb54c508c4bee636d1b3a42>:0
	I MonoDroid:   at Xamarin.Forms.Platform.Android.AppCompat.Platform.SetPageInternal (Xamarin.Forms.Page newRoot) [0x00061] in <9d12bb15abb54c508c4bee636d1b3a42>:0
	I MonoDroid:   at Xamarin.Forms.Platform.Android.AppCompat.Platform.SetPage (Xamarin.Forms.Page newRoot) [0x000e6] in <9d12bb15abb54c508c4bee636d1b3a42>:0
	I MonoDroid:   at Xamarin.Forms.Platform.Android.FormsAppCompatActivity.InternalSetPage (Xamarin.Forms.Page page) [0x0003f] in <9d12bb15abb54c508c4bee636d1b3a42>:0
	I MonoDroid:   at Xamarin.Forms.Platform.Android.FormsAppCompatActivity.SetMainPage () [0x0000c] in <9d12bb15abb54c508c4bee636d1b3a42>:0
	I MonoDroid:   at Xamarin.Forms.Platform.Android.FormsAppCompatActivity.LoadApplication (Xamarin.Forms.Application application) [0x00140] in <9d12bb15abb54c508c4bee636d1b3a42>:0
	I MonoDroid:   at SwipeViewDemo.Droid.MainActivity.OnCreate (Android.OS.Bundle savedInstanceState) [0x00035] in <15e30af50bb64ff6b6d20ac6fd546763>:0
	I MonoDroid:   at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x0000f] in <515e813169e54876823978ab785f569a>:0
	I MonoDroid:   at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.7(intptr,intptr,intptr)

Note that the type name as seen by the native code via
`mono_get_type_name_full()` is:

	Xamarin.Forms.Platform.Android.AppCompat.FormsFragmentPagerAdapter`1[T], Xamarin.Forms.Platform.Android

while `Mono.Android.dll` expects to be looking for:

	Xamarin.Forms.Platform.Android.AppCompat.FormsFragmentPagerAdapter`1, Xamarin.Forms.Platform.Android

This discrepancy was caused by calling `mono_get_type_name_full()`
with its format parameter set to `MONO_TYPE_NAME_FORMAT_REFLECTION`,
while we needed the format value of `MONO_TYPE_NAME_FORMAT_FULL_NAME`.
dellis1972 pushed a commit that referenced this pull request May 12, 2020
…otnet#4673)

Fixes: dotnet#4596
Context: a017561
Context: https://gist.github.com/pjcollins/87762e81f1f3c7e8b821356e4612eecf

A missing parameter in a call to `log_debug` added iFixes: dotnet#4596
Context: a017561
Context: https://gist.github.com/pjcollins/87762e81f1f3c7e8b821356e4612eecf

A missing parameter in a call to `log_debug()` added in a017561 may
lead to a segfault when `assembly` log category and `debug` log level
are enabled:

	F libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x3 in tid 922 (DrawableTinting), pid 922 (DrawableTinting)
	I crash_dump64: obtaining output fd from tombstoned, type: kDebuggerdTombstone
	I /system/bin/tombstoned: received crash request for pid 922
	I crash_dump64: performing dump of process 922 (target tid = 922)
	F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
	F DEBUG   : Build fingerprint: 'Android/sdk_phone_x86_64/generic_x86_64:9/PSR1.180720.012/4923214:userdebug/test-keys'
	F DEBUG   : Revision: '0'
	F DEBUG   : ABI: 'x86_64'
	F DEBUG   : pid: 922, tid: 922, name: DrawableTinting  >>> com.xamarin.DrawableTinting <<<
	F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x3
	F DEBUG   : Cause: null pointer dereference
	F DEBUG   :     rax 0000000000000000  rbx 00007ffed3c283c0  rcx 0000000000000003  rdx 0000000000000002
	F DEBUG   :     r8  00007ffed3c283c0  r9  00000000ffffffff  r10 00007ffed3c283d0  r11 00007ffed3c28824
	F DEBUG   :     r12 00007c88774a2f17  r13 00000000ffffffff  r14 0000000000000000  r15 00007ffed3c283d0
	F DEBUG   :     rdi 0000000000000003  rsi 00007ffed3c283bb
	F DEBUG   :     rbp 00007ffed3c28f18  rsp 00007ffed3c28288  rip 00007c890f860761
	F DEBUG   :
	F DEBUG   : backtrace:
	F DEBUG   :     #00 pc 0000000000020761  /system/lib64/libc.so (strlen+17)
	F DEBUG   :     #1 pc 000000000006e761  /system/lib64/libc.so (__vfprintf+5953)
	F DEBUG   :     #2 pc 000000000008df5d  /system/lib64/libc.so (vsnprintf+189)
	F DEBUG   :     #3 pc 0000000000007b60  /system/lib64/liblog.so (__android_log_vprint+64)
	F DEBUG   :     #4 pc 000000000001350c  /data/app/com.xamarin.DrawableTinting-zvchh4ya_DW11GfpEPFICw==/lib/x86_64/libmonodroid.so (log_debug_nocheck(_LogCategories, char const*, ...)+204)
	F DEBUG   :     #5 pc 000000000000de6a  /data/app/com.xamarin.DrawableTinting-zvchh4ya_DW11GfpEPFICw==/lib/x86_64/libmonodroid.so (xamarin::android::internal::EmbeddedAssemblies::typemap_java_to_managed(char const*)+538)
	F DEBUG   :     #6 pc 000000000000df13  /data/app/com.xamarin.DrawableTinting-zvchh4ya_DW11GfpEPFICw==/lib/x86_64/libmonodroid.so (xamarin::android::internal::EmbeddedAssemblies::typemap_java_to_managed(_MonoString*)+99)
	F DEBUG   :     #7 pc 00000000000d57f8  <anonymous:0000000042d04000>

Add the missing parameter to prevent the `SIGSEGV` from happening.n a017561 may lead
to a segfault when `assembly` log category and `debug` log level are
enabled:

		F libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x3 in tid 922 (DrawableTinting), pid 922 (DrawableTinting)
		I crash_dump64: obtaining output fd from tombstoned, type: kDebuggerdTombstone
		I /system/bin/tombstoned: received crash request for pid 922
		I crash_dump64: performing dump of process 922 (target tid = 922)
		F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
		F DEBUG   : Build fingerprint: 'Android/sdk_phone_x86_64/generic_x86_64:9/PSR1.180720.012/4923214:userdebug/test-keys'
		F DEBUG   : Revision: '0'
		F DEBUG   : ABI: 'x86_64'
		F DEBUG   : pid: 922, tid: 922, name: DrawableTinting  >>> com.xamarin.DrawableTinting <<<
		F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x3
		F DEBUG   : Cause: null pointer dereference
		F DEBUG   :     rax 0000000000000000  rbx 00007ffed3c283c0  rcx 0000000000000003  rdx 0000000000000002
		F DEBUG   :     r8  00007ffed3c283c0  r9  00000000ffffffff  r10 00007ffed3c283d0  r11 00007ffed3c28824
		F DEBUG   :     r12 00007c88774a2f17  r13 00000000ffffffff  r14 0000000000000000  r15 00007ffed3c283d0
		F DEBUG   :     rdi 0000000000000003  rsi 00007ffed3c283bb
		F DEBUG   :     rbp 00007ffed3c28f18  rsp 00007ffed3c28288  rip 00007c890f860761
		F DEBUG   :
		F DEBUG   : backtrace:
		F DEBUG   :     #00 pc 0000000000020761  /system/lib64/libc.so (strlen+17)
		F DEBUG   :     #1 pc 000000000006e761  /system/lib64/libc.so (__vfprintf+5953)
		F DEBUG   :     #2 pc 000000000008df5d  /system/lib64/libc.so (vsnprintf+189)
		F DEBUG   :     #3 pc 0000000000007b60  /system/lib64/liblog.so (__android_log_vprint+64)
		F DEBUG   :     #4 pc 000000000001350c  /data/app/com.xamarin.DrawableTinting-zvchh4ya_DW11GfpEPFICw==/lib/x86_64/libmonodroid.so (log_debug_nocheck(_LogCategories, char const*, ...)+204)
		F DEBUG   :     #5 pc 000000000000de6a  /data/app/com.xamarin.DrawableTinting-zvchh4ya_DW11GfpEPFICw==/lib/x86_64/libmonodroid.so (xamarin::android::internal::EmbeddedAssemblies::typemap_java_to_managed(char const*)+538)
		F DEBUG   :     #6 pc 000000000000df13  /data/app/com.xamarin.DrawableTinting-zvchh4ya_DW11GfpEPFICw==/lib/x86_64/libmonodroid.so (xamarin::android::internal::EmbeddedAssemblies::typemap_java_to_managed(_MonoString*)+99)
		F DEBUG   :     #7 pc 00000000000d57f8  <anonymous:0000000042d04000>

Add the missing parameter to prevent the `SIGSEGV` from happening.
dellis1972 pushed a commit that referenced this pull request Jun 1, 2020
Fixes: dotnet#4713

Context: mono/mono@10795da1c065c
Context: mono/mono@8c085a99b32e9

Changes: mono/mono@075c3f0...8c085a9

  * mono/mono@8c085a99b32: [reflection] Check whether a pointer is valid before dereferencing (#19842)
  * mono/mono@89d772a3abb: Always include Unicode charinfo, so tar made in csc mode works in mcs mode (#19813)
  * mono/mono@e9d3af508e4: Bump bockbuild to get mono/bockbuild#159
  * mono/mono@d6f0c25d34d: [2020-02] Bump msbuild to track mono-2019-12 (#19661)

Whenever Xamarin.Android runtime needs to instantiate a managed type,
it first looks it up by calling:

	MonoType *type = mono_reflection_type_from_name ("MyType, Assembly", nullptr);

The `nullptr` pointer refers to an instance of the Mono `MonoImage`
structure and if `nullptr`, it should cause Mono to find the correct
image containing the type and load it, if not already loaded.

The pointer is propagated down the call chain inside Mono and due to
one of the functions called not properly validating its arguments, the
`nullptr` pointer was dereferenced, leading to a crash similar to:

	libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4c0 in tid 11029 (ompanyname.app3), pid 11029 (ompanyname.app3)
	crash_dump64: obtaining output fd from tombstoned, type: kDebuggerdTombstone
	/system/bin/tombstoned: received crash request for pid 11029
	crash_dump64: performing dump of process 11029 (target tid = 11029)
	DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
	DEBUG   : Build fingerprint: 'google/sdk_gphone_x86_64/generic_x86_64:10/QSR1.190920.001/5891938:user/release-keys'
	DEBUG   : Revision: '0'
	DEBUG   : ABI: 'x86_64'
	DEBUG   : Timestamp: 2020-05-25 14:45:29+0200
	DEBUG   : pid: 11029, tid: 11029, name: ompanyname.app3  >>> com.companyname.app3 <<<
	DEBUG   : uid: 10134
	DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4c0
	DEBUG   : Cause: null pointer dereference
	DEBUG   :     rax 000000000000002f  rbx 0000000000000001  rcx 0000000000000000  rdx 0000000000000030
	DEBUG   :     r8  0000000000000003  r9  000000000013e2e2  r10 0173eed800000000  r11 0000000000000206
	DEBUG   :     r12 0000000000000000  r13 00007478530343c0  r14 00007478075eda33  r15 000074780763efb0
	DEBUG   :     rdi 0000000000000000  rsi 00007478e2cb14d0
	DEBUG   :     rbp 00007ffef3a35680  rsp 00007ffef3a355d0  rip 0000747807a4066a
	DEBUG   :
	DEBUG   : backtrace:
	DEBUG   :       #00 pc 00000000003ba66a  /data/app/com.companyname.app3-aQUF6Ge6_v-WaLb5i8Q7vw==/lib/x86_64/libmonosgen-2.0.so (_mono_reflection_get_type_from_info+474)
	DEBUG   :       #1 pc 00000000003ba3d1  /data/app/com.companyname.app3-aQUF6Ge6_v-WaLb5i8Q7vw==/lib/x86_64/libmonosgen-2.0.so (mono_reflection_type_from_name_checked+321)
	DEBUG   :       #2 pc 00000000003ba26d  /data/app/com.companyname.app3-aQUF6Ge6_v-WaLb5i8Q7vw==/lib/x86_64/libmonosgen-2.0.so (mono_reflection_type_from_name+125)
	DEBUG   :       #3 pc 000000000000ddb5  /data/app/com.companyname.app3-aQUF6Ge6_v-WaLb5i8Q7vw==/lib/x86_64/libmonodroid.so (xamarin::android::internal::EmbeddedAssemblies::typemap_java_to_managed(char const*)+389) (BuildId: 9952f1cfe0d910ae631abc73479f88eef34fd71d)
	DEBUG   :       #4 pc 000000000000def3  /data/app/com.companyname.app3-aQUF6Ge6_v-WaLb5i8Q7vw==/lib/x86_64/libmonodroid.so (xamarin::android::internal::EmbeddedAssemblies::typemap_java_to_managed(_MonoString*)+99) (BuildId: 9952f1cfe0d910ae631abc73479f88eef34fd71d)
	DEBUG   :       #5 pc 0000000000069532  <anonymous:5ad25000>

Mono commit mono/mono@10795da1c06 fixes this issue.
dellis1972 pushed a commit that referenced this pull request Dec 5, 2020
…5365)

Context: dotnet#5167

The `Android.Runtime.Extensions` type is not accessed via reflection.

It *is* preserved by the linker when needed, e.g.:

	$ illinkanalyzer -r Android.Runtime.Extensions linker-dependencies.xml.gz
	…
	--- Method:TResult Android.Runtime.Extensions::JavaCast(Android.Runtime.IJavaObject) dependencies ---
	Dependency #1
	        Method:TResult Android.Runtime.Extensions::JavaCast(Android.Runtime.IJavaObject)
	        | MethodSpec:TResult Android.Runtime.Extensions::JavaCast<T>(Android.Runtime.IJavaObject) [1 deps]
	        | Method:T Android.App.Activity::FindViewById(System.Int32) [1 deps]
	        | MethodSpec:!!0 Android.App.Activity::FindViewById<Android.Widget.Button>(System.Int32) [1 deps]
	        | Method:System.Void UnnamedProject.MainActivity::OnCreate(Android.OS.Bundle) [2 deps]
	        | Assembly:UnnamedProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null [1 deps]
	        | Other:Copy
	…
dellis1972 pushed a commit that referenced this pull request Dec 10, 2020
…otnet#4966)

Context: dotnet#1218 (comment)

The undocumented, experimental, `Hybrid` value for the
`$(AndroidAotMode)` MSBuild property is not currently compatible with
the armeabi-v7a target ABI.  Attempting to run an app built with
`$(AndroidAotMode)`=`Hybrid` in an armeabi-v7a environment results in
a crash:

	F libc    : Fatal signal 11 (SIGSEGV), code 2, fault addr 0x913a50c8 in tid 31140 (ppxamarinforms1)
	W         : debuggerd: handling request: pid=31140 uid=10146 gid=10146 tid=31140
	F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
	F DEBUG   : Build fingerprint: 'motorola/perry_metropcs_c/perry:7.1.1/NCQS26.69-64-21/33:user/release-keys'
	F DEBUG   : Revision: 'p3b0'
	F DEBUG   : ABI: 'arm'
	F DEBUG   : pid: 31140, tid: 31140, name: ppxamarinforms1  >>> com.companyname.mobileappxamarinforms1 <<<
	F DEBUG   : signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x913a50c8
	F DEBUG   :     r0 be9384d4  r1 00000000  r2 be9385a0  r3 9320b1c0
	F DEBUG   :     r4 00000000  r5 94167208  r6 00000000  r7 be938584
	F DEBUG   :     r8 be938838  r9 ae040008  sl 00000000  fp be9385a0
	F DEBUG   :     ip 913a50c8  sp be9384e4  lr 942a8420  pc 913a50c8  cpsr 000f0010
	F DEBUG   :
	F DEBUG   : backtrace:
	F DEBUG   :     #00 pc 000250c8  [anon:libc_malloc:91380000]
	F DEBUG   :     #1 pc 0000141c  <anonymous:942a7000>
	W ActivityManager: Activity pause timeout for ActivityRecord{7ded4d1 u0 com.companyname.mobileappxamarinforms1/crc64e53dff5578afb8f2.MainActivity t5740}
	I ActivityManager: Killing 30471:com.google.android.apps.fireball/u0a145 (adj 906): empty #13
	D ConnectivityService: ConnectivityService NetworkRequestInfo binderDied(NetworkRequest [ LISTEN id=624, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&FOREGROUND] ], android.os.BinderProxy@f4c4e10)
	D ActivityManager: cleanUpApplicationRecord -- 30471
	E ConnectivityService: RemoteException caught trying to send a callback msg for NetworkRequest [ LISTEN id=624, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&FOREGROUND] ]
	W         : debuggerd: resuming target 31140
	I BootReceiver: Copying /data/tombstones/tombstone_05 to DropBox (SYSTEM_TOMBSTONE)
	W ActivityManager:   Force finishing activity com.companyname.mobileappxamarinforms1/crc64e53dff5578afb8f2.MainActivity
	I Zygote  : Process 31140 exited due to signal (11)

Since it is known that this configuration currently produces a crash,
emit a build error for it to improve the visibility of the known
issue and reduce the time users might spend searching for the cause
of the crash.

Other changes:

Update the `HybridAOT` test to cover the new error.

Correct the `IncrementalBuildTest.BuildIncrementalAot()` test so that
it sets `$(AndroidSupportedAbis)`.  A side effect is that the test
cases that use `$(AndroidAotMode)`=`Full` now build successfully.
Note that although those test cases now build successfully, the
resulting app packages abort when run on device because Xamarin.Android
requires JIT compilation:

	Unhandled Exception:
	System.ExecutionEngineException: Attempting to JIT compile method '(wrapper other) void Java.Interop.JavaVMInterface:PtrToStructure (intptr,object)' while running in aot-only mode.

TODO: Add a build error for `$(AndroidAotMode)`=`Full`, likely by
updating error XA3002.
dellis1972 pushed a commit that referenced this pull request Feb 12, 2021
Changes: xamarin/NRefactory@0607a4a...495405a

  * xamarin/NRefactory@495405a6: Merge pull request #2 from jpobst/sdk-style
  * xamarin/NRefactory@e4d5997e: Update some project files to SDK-style.
  * xamarin/NRefactory@60ac8e99: Merge pull request #1 from xamarin/cecilPackageReference
  * xamarin/NRefactory@c2c07caa: Switch Cecil reference to PackageReference.

We are working on using `dotnet build` to build `Xamarin.Android.sln`
and `Xamarin.Android-Tests.sln`.  `dotnet build` requires that all
projects be SDK-style short-form projects.

The `tests/MSBuildDeviceIntegration` integration tests use NRefactory
as part of the debugger tests, to ensure that the debugger can attach
to an app on-device.  In order for `tests/MSBuildDeviceIntegration`
to be buildable with `dotnet build`, NRefactory must have SDK-style
`.csproj` files.

Unfortunately, the [icsharpcode/NRefactory][0] repo only contains
"long-form" projects, has been archived, and is now read-only.

Switch to the [xamarin/NRefactory][1] repo, which is *not* archived
and is maintained by the VSMac team, and bump to a commit which
includes xamarin/NRefactory@e4d5997e, which migrates many of the
`.csproj` files to SDK-style short-form projects.

This allows us to continue our `dotnet build` explorations.

[0]: https://github.com/icsharpcode/NRefactory
[1]: https://github.com/xamarin/NRefactory
dellis1972 pushed a commit that referenced this pull request Feb 19, 2021
…otnet#5623)

Context: dotnet#5619

It appears that Xamarin.Android application uploaded to
Google Play Console internal Test Track can fail the pre-launch test
because the `MonodroidRuntime::get_java_class_name_for_TypeManager()`
method can sometimes get a `nullptr` Java class name from JNI:

	Build fingerprint: 'google/blueline/blueline:9/PQ3A.190801.002/5670241:user/release-keys'
	Revision: 'MP1.0'
	ABI: 'arm64'
	pid: 15773, tid: 15773, name: com.Myapp  >>> com.Myapp<<<
	signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
	Cause: null pointer dereference
	    x0  0000000000000000  x1  0000000000000000  x2  0000000000000000  x3  00000000000000e1
	    x4  0000000000000000  x5  0000000000000305  x6  0000000000000006  x7  0000000000000010
	    x8  0101010101010101  x9  4adfd1b7ed2e23e2  x10 0000000000430000  x11 000000000000000a
	    x12 0000000000000002  x13 0000000000000001  x14 00000000000000a8  x15 000000000000000a
	    x16 0000007f703f00f8  x17 0000007f7031f290  x18 0000000000000008  x19 0000000000000000
	    x20 0000007eecae0460  x21 0000000000000000  x22 0000000000000000  x23 0000000000000099
	    x24 0000000000000085  x25 0000007eecb30010  x26 0000000000000099  x27 0000000000000000
	    x28 0000007f724255e0  x29 0000007fe01ad010
	    sp  0000007fe01acff0  lr  0000007f7036f3b4  pc  0000007f7031f2a0
	backtrace:
	    #00 pc 000000000001e2a0  /system/lib64/libc.so (strlen+16)
	    #1 pc 000000000006e3b0  /system/lib64/libc.so (strdup+20)
	    #2 pc 000000000000d4e8  /data/app/com.Myapp-1lufsJe3FIZ0YHoEAB08KA==/split_config.arm64_v8a.apk (offset 0x165d000) (xamarin::android::internal::MonodroidRuntime::get_java_class_name_for_TypeManager(_jclass*)+92)
	    #3 pc 000000000005f6d0  <anonymous:0000007ecc4ac000>

This can happen if either one of the below points is true:

 1. [`java.lang.Class.getName()`][0] returns `nullptr`
    (a nameless class?  This seems unlikely.)
 2. [`JNIEnv::GetStringUTFChars()`][1] returns `nullptr`
    (a memory allocation failure?)

Of these, (2) appears to be most probable; regardless, add appropriate
`nullptr` checks for each of them, failing gracefully instead of
segfaulting.

This is NOT a fix for the original problem as we don't know by what
it is caused but, nevertheless, the `nullptr` check should be there.

[0]: https://developer.android.com/reference/java/lang/Class?hl=en#getName()
[1]: https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#GetStringUTFChars
dellis1972 pushed a commit that referenced this pull request Apr 14, 2021
dotnet#5811)

Context: dotnet#5838

This reverts commit d13d0f9.

Commit d13d0f9 inadvertently broke the
[`DebuggingTest.ClassLibraryMainLauncherRuns()` unit test][0], when
using a test app which:

 1. Uses .NET 6, which -- because of d13d0f9 -- sets
    `$(AndroidEnablePreloadAssemblies)`=False by default -- with-

 2. A "Debug" build (Fast Deployment enabled), with-

 3. `$(AndroidLinkResources)`=False (the default; see also 9e6ce03),
    and-

 4. launching the app, which

 5. Loads an `Activity` subclass located in an assembly which is
    *not* the "main" App assembly

then the app crashes during process startup:

	android.runtime.JavaProxyThrowable: System.NullReferenceException: Object reference not set to an instance of an object
	    at MyLibrary.MainActivity.OnCreate(Bundle bundle)
	    at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_(IntPtr jnienv, IntPtr native__this, IntPtr native_savedInstanceState)
	    at com.xamarin.classlibrarymainlauncherruns.MainActivity.n_onCreate(Native Method)
	    at com.xamarin.classlibrarymainlauncherruns.MainActivity.onCreate(MainActivity.java:29)

The cause of the crash is that, because not all assemblies are loaded
as part of process startup -- the whole *point* to d13d0f9 and
defaulting `$(AndroidEnablePreloadAssemblies)`=False -- then
[`ResourceIdManager.UpdateIdValues()`][1] isn't able to update all
fields in all `Resource` types to have the values from the app's
`Resource.designer.cs` file.  Consequently, the values *may* be
invalid, and thus the `NullReferenceException`.

As an "immediate" fix is not quickly forthcoming -- though enabling
`$(AndroidLinkResources)`=False *by default* is an "interesting"
solution, with unknown inner dev loop performance implications --
we're reverting commit d13d0f9.

Issue dotnet#5838 will track the re-enabling of
`$(AndroidEnablePreloadAssemblies)`=False by default in .NET 6 apps.

~~~

Additionally, update `DebuggingTest.ClassLibraryMainLauncherRuns()`
so that `Resources\layout\foo.xml` contains *valid* layout XML.
It was originally:

	<?xml version="1.0" encoding="utf-8" ?>
	<LinearLayout
	  xmlns:android="http://schemas.android.com/apk/res/android"
	/>

which would crash with:

	Java.Lang.RuntimeException: Unable to start activity ComponentInfo{com.xamarin.classlibrarymainlauncherruns/com.xamarin.classlibrarymainlauncherruns.MainActivity}:
	  android.view.InflateException: Binary XML file line #1 in com.xamarin.classlibrarymainlauncherruns:layout/foo: Binary XML file line #1: You must supply a layout_width attribute.
	---> Android.Views.InflateException: Binary XML file line #1 in com.xamarin.classlibrarymainlauncherruns:layout/foo: Binary XML file line #1: You must supply a layout_width attribute.
	---> Java.Lang.UnsupportedOperationException: Binary XML file line #1: You must supply a layout_width attribute.
	--- End of managed Java.Lang.UnsupportedOperationException stack trace ---
	java.lang.UnsupportedOperationException: Binary XML file line #1: You must supply a layout_width attribute.

because the layout XML was, in fact, invalid, as it wasn't providing
the required `android:layout_width` attribute.

Update `foo.xml` so that it has valid layout XML:

	<?xml version="1.0" encoding="utf-8"?>
	<LinearLayout
	  xmlns:android="http://schemas.android.com/apk/res/android"
	  android:layout_width="fill_parent"
	  android:layout_height="wrap_content"
	/>"

This way we won't be chasing invalid XML going forward.

The above `UnsupportedOperationException` *hid* the
`NullReferenceException` in d13d0f9; the `NullReferenceException`
wasn't visible until after the invalid XML was fixed.

[0]: https://github.com/xamarin/xamarin-android/blob/bf4f4f42af26cdddb46087deed59aae8424f7942/tests/MSBuildDeviceIntegration/Tests/DebuggingTest.cs#L74-L124
[1]: https://github.com/xamarin/xamarin-android/blob/bf4f4f42af26cdddb46087deed59aae8424f7942/src/Mono.Android/Android.Runtime/ResourceIdManager.cs#L9-L31
dellis1972 pushed a commit that referenced this pull request Jun 1, 2021
)

Changes: dotnet/installer@f442964...3ebe0ca
Changes: dotnet/linker@7a5c445...620b243
Changes: dotnet/runtime@6430375...5a26d12

Context: https://github.com/dotnet/sdk/blob/1f544a59270cecb2947e50a01f7056c685b4e319/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets#L389-L392
Context: dotnet#5954 (comment)
Context: dotnet#5669 (comment)
 
Updates:
 
  * Microsoft.Dotnet.Sdk.Internal:
    [from 6.0.100-preview.5.21266.3 to 6.0.100-preview.6.21276.2][0]

  * Microsoft.NET.ILLink.Tasks:
    [from 6.0.100-preview.5.21264.1 to 6.0.100-preview.6.21275.1][1]

  * Microsoft.NETCore.App.Ref:
    [from 6.0.0-preview.5.21265.5 to 6.0.0-preview.6.21274.1][2]
 
Update `.apkdesc` files, as `System.Net.Quic.dll` is now included
in the Xamarin.Forms sample.

Fix `azure-pipelines.yaml` so that if (when) the
`Mono.Android.NET_Tests` unit tests fail, the corresponding `.apk`
or `.aab` file is uploaded for our later investigation; see also
commit af7f7f5, which contained a "typo" such that .NET 6 packages
*weren't* uploaded on unit test failure, as they used the wrong
target framework identifier in the path.

Finally, and most annoying of all, the `$(InvariantGlobalization)`
MSBuild property should *not* default to `false` in .NET 6 projects,
as was introduced in commit 9ac280c, but instead should default
to *the empty string*.

The problem is due to [`Microsoft.NET.Sdk.targets`][3]:

	<RuntimeHostConfigurationOption
	    Condition=" '$(InvariantGlobalization)' != '' "
	    Include="System.Globalization.Invariant"
	    Value="$(InvariantGlobalization)"
	    Trim="true"
	/>

The above fragment sets `%(RuntimeHostConfigurationOption.Trim)` to
`True` for `System.Globalization.Invariant` whenever
`$(InvariantGlobalization)` is *not* the empty string.

The value `false` is *not* the empty string.

This caused `System.Globalization.Invariant`-related trim features
to be enabled, which had the unfortunate and unanticipated side effect
of causing ICU to *not* be properly initialized when running the
`Mono.Android.NET_Tests` unit test apps, which resulted in a SIGSEGV:

	libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 31880 (droid.NET_Tests), pid 31880 (droid.NET_Tests)
	crash_dump64: obtaining output fd from tombstoned, type: kDebuggerdTombstone
	tombstoned: received crash request for pid 31880
	crash_dump64: performing dump of process 31880 (target tid = 31880)
	DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
	DEBUG   : Build fingerprint: 'google/redfin/redfin:11/RQ1A.201205.011/6966805:user/release-keys'
	DEBUG   : Revision: 'MP1.0'
	DEBUG   : ABI: 'arm64'
	DEBUG   : Timestamp: 2021-05-26 15:21:42-0400
	DEBUG   : pid: 31880, tid: 31880, name: droid.NET_Tests  >>> Mono.Android.NET_Tests <<<
	DEBUG   : uid: 10282
	DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
	DEBUG   : Cause: null pointer dereference
	DEBUG   :     x0  b400007c4de52530  x1  0000007fcc4cbeec  x2  fffffffffffffff0  x3  b400007d2de37c80
	DEBUG   :     x4  b400007d2de37cf0  x5  0000000000000004  x6  0000007c2225ddac  x7  0000007fcc4cbfe0
	DEBUG   :     x8  0000000000000000  x9  000000001333c921  x10 0000000000000000  x11 000000002de37cf0
	DEBUG   :     x12 000000002a742e66  x13 0000000000000012  x14 0000000000000200  x15 0000000000000011
	DEBUG   :     x16 0000007bd6adb810  x17 0000007ed2056240  x18 0000007ed3b94000  x19 0000007fcc4cc040
	DEBUG   :     x20 b400007c4de52530  x21 b400007c4de52530  x22 0000000000000000  x23 b400007d7de490c0
	DEBUG   :     x24 0000000000000001  x25 0000007bd58055c0  x26 0000007bd5cc0130  x27 0000007ed33ab000
	DEBUG   :     x28 0000007bd6af1000  x29 0000007fcc4cbf00
	DEBUG   :     lr  0000007bd69119c8  sp  0000007fcc4cbee0  pc  0000000000000000  pst 0000000080001000
	…
	DEBUG   : backtrace:
	DEBUG   :       #00 pc 0000000000000000  <unknown>
	DEBUG   :       #1 pc 000000000014e9c4  /data/app/~~oruJhhqj_EC_NWSaIGF_RQ==/Mono.Android.NET_Tests-G1iNxUwmGyu-tDRqYcK94g==/lib/arm64/libmonosgen-2.0.so (GlobalizationNative_GetSortHandle+76) (BuildId: 869ce5526fa884035199acac4ddc81bb6eeaf134)
	DEBUG   :       #2 pc 000000000000ddbc  <anonymous:7c22250000>

While we've (inadvertently) had `%(Trim)` enabled for over three
months now, the *trigger* for this particular crash appears to be
commit dotnet/runtime@bc27d49, which moved ICU initialization outside
of the `GlobalizationMode` static constructor and into a new
`GlobalizationMode.Settings` static constructor…which wasn't executed.

Explicitly setting `$(InvariantGlobalization)` to the empty string
*unless* it is the value `true` allows us to avoid setting
`%(RuntimeHostConfigurationOption.Trim)`=True for
`System.Globalization.Invariant`, which in turn avoids whatever set
of linker-induced changes were preventing ICU from being properly
initialized, which avoids the SIGSEGV.

Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Peppers <jonathan.peppers@microsoft.com>
Co-authored-by: Peter Collins <pecolli@microsoft.com>
 
[0]: dotnet/installer@f442964...3ebe0ca
[1]: dotnet/linker@7a5c445...620b243
[2]: dotnet/runtime@6430375...5a26d12
[3]: https://github.com/dotnet/sdk/blob/1f544a59270cecb2947e50a01f7056c685b4e319/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets#L389-L392
dellis1972 pushed a commit that referenced this pull request Aug 27, 2021
)

Fixes: dotnet#6211

Mono VM will return a valid AppDomain pointer (both in "legacy" and
NET6 cases) only if the current thread is attached to some domain.
It is possible that when managed code is called from an unattached
Java thread, `mono_domain_get()` will return `nullptr` instead of a
valid one.  If we further pass `nullptr` to other Mono functions, a
segfault may occur if Mono fails to validate the passed pointer.

Sample code which may trigger the problem:

	public override void OnCreate()
	{
	   AppDomain.CurrentDomain.UnhandledException += (sender, e) => {
	       Console.WriteLine("!!! UnhandledException: " + e.ExceptionObject.GetType().FullName);
	   };
	   base.OnCreate();
	}

	protected override void OnStart()
	{
	    base.OnStart();
	    Java.Util.Concurrent.Executors.NewSingleThreadExecutor()
	        .Execute(new Runnable(() => {
	            throw new Exception("Exception from Java Executor!");
	        }));
	}

Possible crash caused by the above code:

	F libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xb8 in tid 19241 (pool-1-thread-1), pid 19214 (ndroidcrashtest)
	F DEBUG   : backtrace:
	I hwservicemanager: getTransport: Cannot find entry android.hardware.graphics.mapper@3.0::IMapper/default in either framework or device manifest.
	F DEBUG   :       #00 pc 0011b72f  /apex/com.android.runtime/lib/bionic/libc.so (pthread_mutex_lock+31) (BuildId: 471745f0fbbcedb3db1553d5bd6fcd8b)
	F DEBUG   :       #1 pc 0015240d  /data/app/com.companyname.androidcrashtest-sqgk-Mnu8GZM5hKPu1yWEQ==/lib/x86/libmonosgen-2.0.so (mono_domain_assembly_search+61)

	F libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xb8 in tid 19763 (pool-1-thread-1), pid 19737 (ndroidcrashtest)
	F DEBUG   : backtrace:
	F DEBUG   :       #00 pc 0011b72f  /apex/com.android.runtime/lib/bionic/libc.so (pthread_mutex_lock+31) (BuildId: 471745f0fbbcedb3db1553d5bd6fcd8b)
	F DEBUG   :       #1 pc 0026b91a  /data/app/com.companyname.androidcrashtest-JQoYc3YFwZtEoSJlTqX_BA==/lib/x86/libmonosgen-2.0.so (mono_os_mutex_lock+42)

To avoid the above situation, wrap the `mono_domain_get()` call into
`utils.get_current_domain()` which checks the return value of
`mono_domain_get()` and, if it's `nullptr`, calls
`mono_get_root_domain()` and attaches the current thread to that
root domain.
dellis1972 pushed a commit that referenced this pull request Nov 8, 2021
)

Context: dotnet#6420 (comment)

Clang's AddressSanitizer detected the following:

	Mono.Android_Tests: ==2488==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x8a600774 at pc 0xaeee9982 bp 0xbf98dc68 sp 0xbf98dc60
	Mono.Android_Tests: WRITE of size 4 at 0x8a600774 thread T0
	Mono.Android_Tests:     #0 0xaeee9981  (/data/app/Mono.Android_Tests-1/lib/x86/libmonodroid.so+0x38981)
	Mono.Android_Tests:     #1 0xaeef92d9  (/data/app/Mono.Android_Tests-1/lib/x86/libmonodroid.so+0x482d9)
	Mono.Android_Tests:     #2 0xaef009ae  (/data/app/Mono.Android_Tests-1/lib/x86/libmonodroid.so+0x4f9ae)
	Mono.Android_Tests:     #3 0xaef06d14  (/data/app/Mono.Android_Tests-1/lib/x86/libmonodroid.so+0x55d14)
	Mono.Android_Tests: 0x8a600774 is located 0 bytes to the right of 4-byte region [0x8a600770,0x8a600774)
	Mono.Android_Tests: allocated by thread T0 here:
	Mono.Android_Tests:     #0 0xaedbe925  (/data/app/Mono.Android_Tests-1/lib/x86/libclang_rt.asan-i686-android.so+0xb6925)
	Mono.Android_Tests:     #1 0xaeee9ae1  (/data/app/Mono.Android_Tests-1/lib/x86/libmonodroid.so+0x38ae1)
	Mono.Android_Tests:     #2 0xaeee9751  (/data/app/Mono.Android_Tests-1/lib/x86/libmonodroid.so+0x38751)
	Mono.Android_Tests:     #3 0xaeef92d9  (/data/app/Mono.Android_Tests-1/lib/x86/libmonodroid.so+0x482d9)
	Mono.Android_Tests:     #4 0xaef009ae  (/data/app/Mono.Android_Tests-1/lib/x86/libmonodroid.so+0x4f9ae)
	Mono.Android_Tests:     #5 0xaef06d14  (/data/app/Mono.Android_Tests-1/lib/x86/libmonodroid.so+0x55d14)
	Mono.Android_Tests:     #6 0xb30cb970  (/data/dalvik-cache/x86/data@app@Mono.Android_Tests-1@base.apk@classes.dex+0x5c970)
	Mono.Android_Tests: SUMMARY: AddressSanitizer: heap-buffer-overflow (/data/app/Mono.Android_Tests-1/lib/x86/libmonodroid.so+0x38981)

Address of the offending region points to
`BasicUtilities::monodroid_strsplit()` and is likely the line
modified in this commit.  Append terminating `nullptr` to `vector`
instead of overwriting the last element.
dellis1972 pushed a commit that referenced this pull request Jan 19, 2022
Commit 6eb11f1 added support for API-32, while keeping the .NET 6
default `$(TargetFramework)` value as `net6.0-android31.0`:

> However, we don't want to change the default API level for .NET 6
> projects; the default will remain `net6.0-android31.0` (API-31),

This appears to have had some unforeseen complications: we would use
the API-31 `Mono.Android.dll`, with the API-32 `libmonodroid.so`/etc.
runtime libraries.  This in turn appears to be responsible for some
crashes we've seen on CI ever since commit c227042 when running the
`Mono.Android.NET_Tests` unit tests under .NET 6 with the interpreter
enabled, because `libxamarin-app.so` and `libmonodroid.so` have ABI
dependencies:

	DOTNET  : JNI_OnLoad: JNI_OnLoad in pal_jni.c
	libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x2 in tid 3666 (droid.NET_Tests), pid 3666 (droid.NET_Tests)
	crash_dump64: performing dump of process 3666 (target tid = 3666)
	DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
	DEBUG   : Build fingerprint: 'Android/sdk_phone_x86_64/generic_x86_64:10/QPP6.190730.005.B1/5775370:userdebug/test-keys'
	DEBUG   : Revision: '0'
	DEBUG   : ABI: 'x86_64'
	DEBUG   : Timestamp: 2022-01-18 16:53:04+0000
	DEBUG   : pid: 3666, tid: 3666, name: droid.NET_Tests  >>> Mono.Android.NET_Tests <<<
	DEBUG   : uid: 10105
	DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x2
	DEBUG   : Cause: null pointer dereference
	DEBUG   :     rax 0000000000002b36  rbx 000078c8afb3f860  rcx 000078c98b6561f0  rdx 0000000000000000
	DEBUG   :     r8  0000000000000002  r9  0000000000000080  r10 000078c98b296080  r11 000078c987d35178
	DEBUG   :     r12 00007fffe46ae99c  r13 000078c8afb89ea0  r14 000078c8afb3f990  r15 000078c98b6746c0
	DEBUG   :     rdi 000078c8afb3f860  rsi 0000000000000002
	DEBUG   :     rbp 0000000000000001  rsp 00007fffe46ae448  rip 000078c8afb1b31c
	main    : type=1400 audit(0.0:40): avc: granted { read } for name="u:object_r:net_dns_prop:s0" dev="tmpfs" ino=6642 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:object_r:net_dns_prop:s0 tclass=file app=Mono.Android.NET_Tests
	DEBUG   : 
	DEBUG   : backtrace:
	DEBUG   :       #00 pc 000000000002c31c  /data/app/Mono.Android.NET_Tests-fbdZV696v1UeW3jUzJg9yg==/lib/x86_64/libmonodroid.so (xamarin::android::Util::monodroid_store_package_name(char const*)+12) (BuildId: 91fe7d9c6b30356fcfb8337b8541d0132df4f44a)
	DEBUG   :       #1 pc 0000000000025bbc  /data/app/Mono.Android.NET_Tests-fbdZV696v1UeW3jUzJg9yg==/lib/x86_64/libmonodroid.so (xamarin::android::internal::MonodroidRuntime::Java_mono_android_Runtime_initInternal(_JNIEnv*, _jclass*, _jstring*, _jobjectArray*, _jstring*, _jobjectArray*, _jobject*, _jobjectArray*, int, unsigned char, unsigned char)+652) (BuildId: 91fe7d9c6b30356fcfb8337b8541d0132df4f44a)
	DEBUG   :       #2 pc 00000000000273fb  /data/app/Mono.Android.NET_Tests-fbdZV696v1UeW3jUzJg9yg==/lib/x86_64/libmonodroid.so (Java_mono_android_Runtime_initInternal+75) (BuildId: 91fe7d9c6b30356fcfb8337b8541d0132df4f44a)
	DEBUG   :       #3 pc 0000000000174641  /apex/com.android.runtime/lib64/libart.so (art_quick_generic_jni_trampoline+209) (BuildId: 8bb3225e7c408f2ca23abac3db0417f2)
	…

Thinking about it more, we should only need to use the API-31 "ref"
or "targeting" pack.  The "runtime" pack can just use the latest from
the workload.

To fix this:

 1. Create new `$(_AndroidTargetingPackId)` and
    `$(_AndroidTargetingPackVersion)` properties to use independently
    of the runtime pack version.

 2. Remove `Microsoft.Android.Runtime.31.[rid]` packs from the workload.

 3. Remove the `android-32` workload, as it should no longer be needed.
    The API 31 "ref" pack is fairly small and can go in the `android`
    workload.

Now our `android` workload is:

  * `Microsoft.Android.Sdk`
  * `Microsoft.Android.Ref.31`
  * `Microsoft.Android.Ref.32`
  * `Microsoft.Android.Runtime.32.android-arm`
  * `Microsoft.Android.Runtime.32.android-arm64`
  * `Microsoft.Android.Runtime.32.android-x86`
  * `Microsoft.Android.Runtime.32.android-x64`
  * `Microsoft.Android.Templates`

After these changes, I get this assembly at build time:

	dotnet\packs\Microsoft.Android.Ref.31\31.0.101-preview.11.117\ref\net6.0\Mono.Android.dll

And this assembly at runtime:

	dotnet\packs\Microsoft.Android.Runtime.32.android-arm64\31.0.200-preview.13.21\runtimes\android-arm64\lib\net6.0\Mono.Android.dll

Additionally, CI is fully green; in particular, the
**APKs .NET - macOS** step is green, which hasn't been true on
xamarin-android/main since commit c227042.
dellis1972 pushed a commit that referenced this pull request Feb 1, 2022
…6672)

Context: dotnet/maui#4262
Context: dotnet#6675

If you run the `maui-blazor` template in a Release build:

	dotnet build -t:Run -c Release

it crashes at runtime:

	D monodroid-assembly: typemap: type with token 33555274 (0x200034a) in module {C7B4CC8F-7A03-4A3F-A34A-DC66EDC548B9} (Mono.Android) corresponds to Java type 'android/runtime/JavaProxyThrowable'
	…
	F DEBUG   : backtrace:
	F DEBUG   : #00 pc 000000000065d8fc  /apex/com.android.art/lib64/libart.so (void art::StackVisitor::WalkStack<(art::StackVisitor::CountTransitions)0>(bool)+156) (BuildId: 7fbaf2a1a3317bd634b00eb90e32291e)
	F DEBUG   : #1 pc 000000000069b25d  /apex/com.android.art/lib64/libart.so (art::Thread::GetCurrentMethod(unsigned int*, bool, bool) const+157) (BuildId: 7fbaf2a1a3317bd634b00eb90e32291e)
	F DEBUG   : #2 pc 0000000000430fed  /apex/com.android.art/lib64/libart.so (art::JNI<false>::FindClass(_JNIEnv*, char const*)+765) (BuildId: 7fbaf2a1a3317bd634b00eb90e32291e)
	F DEBUG   : #3 pc 0000000000047e5a  /data/app/~~0Qm6D1S0sO3f1lwfakN0PA==/com.companyname.mauiapp2-08UokVCH5k_PlbZEH_hhkA==/split_config.x86_64.apk!libmono-android.release.so (offset 0x11e000) (java_interop_jnienv_find_class+26) (BuildId: 3d04f8b946590175e97b89aee2e3b19ceed4b524)
	F DEBUG   : #4 pc 00000000000128ac  <anonymous:41640000>

The crash can be avoided by disabling the linker:

	dotnet build -t:Run -c Release -p:AndroidLinkMode=None
	# -or-
	dotnet build -t:Run -c Release -p:PublishTrimmed=false

However, let us return to the crash: *why* is it crashing?
This isn't a "good debugging experience"; we have no useful context.

Lots of investigation later -- all hail printf debugging -- and we
found that the cause of the crash was an unhandled exception:

 1. `Mono.Android.dll` has it's Java Callable Wrappers generated
    from the *unlinked* assembly, into `mono.android.jar` and
    `mono.android.dex` files.  The Java Callable Wrapper for
    `Android.Runtime.InputStreamAdapter` thus includes *all*
    `Read()` method overloads.

 2. When the app is built in Release configuration, linking is
    enabled, and *some* of the `InputStreamAdapter.Read()` methods
    are removed by the linker, along with the
    `Java.IO.InputStream.Read()` methods that were overridden.

 3. At runtime, we perform [Java Type Registration][0] for the
    `Android.Runtime.InputStreamAdapter` type, which eventually calls
    `AndroidTypeManager.RegisterNativeMembers()`, which eventually
    attempts to *effectively* do:

        Delegate.CreateDelegate (
	        typeof(Func<Delegate>),
	        typeof(InputStreamAdapter),
	        "GetReadHandler");

 4. Because of (2), `Java.IO.InputStream.GetReadHandler()`
    *does not exist*, and thus `Delegate.CreateDelegate()` throws an
    `ArgumentException`.

So far, so reasonable, but…

 5. `AndroidTypeManager.RegisterNativeMembers()` didn't catch any
    exceptions, nor did any other method between the original Java
    `Runtime.register()` invocation and
    `AndroidTypeManager.RegisterNativeMembers()`.  The result is that
    a C# exception was "in flight", and Mono then proceeded to
    *tear down the stack frame* as it unwound the callstack looking
    for `catch` handlers.

At this point, the process is toast: the runtime stack is FUBAR.

This is also why the `backtrace:` is "rooted" in
`JNIEnv::FindClass()`: `JNIEnv::FindClass()` invokes Java static
constructors before returning, which is how the static constructor in
the Java Callable Wrapper for `InputStreamAdapter` called
`Runtime.register()` in the first place.

All of this makes for a miserable debugging experience.

Fixing the "original" linker issue will be done in
dotnet#6675.

This hasn't been an issue in "Classic" Xamarin.Android, presumably
because the classic linker isn't as good as the net6 linker.

What we want to do *here* is improve this debugging experience, by
"wrapping" `AndroidTypeManager.RegisterNativeMembers()` in a
`try`/`catch` block, which can then *marshal the thrown exception*
back to Java.  This *prevents* Mono from unwinding the callstack past
a JNI boundary, and avoids the annoying-to-debug app crash.

After this change, we get a much friendlier unhandled exception crash:

	I MonoDroid: Android.Runtime.JavaProxyThrowable: Exception_WasThrown, Android.Runtime.JavaProxyThrowable
	I MonoDroid:
	I MonoDroid:   --- End of managed Android.Runtime.JavaProxyThrowable stack trace ---
	I MonoDroid: android.runtime.JavaProxyThrowable: System.ArgumentException: Arg_DlgtTargMeth
	I MonoDroid:    at System.Delegate.CreateDelegate(Type , Type , String , Boolean , Boolean )
	I MonoDroid:    at System.Delegate.CreateDelegate(Type , Type , String )
	I MonoDroid:    at Android.Runtime.AndroidTypeManager.RegisterNativeMembers(JniType , Type , String )
	I MonoDroid: --- End of stack trace from previous location ---
	I MonoDroid:    at Java.Interop.JniEnvironment.StaticMethods.CallStaticObjectMethod(JniObjectReference , JniMethodInfo , JniArgumentValue* )
	I MonoDroid:    at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue* )
	I MonoDroid:    at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue[] )
	I MonoDroid:    at Android.Runtime.JNIEnv.FindClass(String )
	I MonoDroid:    at Android.Runtime.JNIEnv.AllocObject(String )
	I MonoDroid:    at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue* )
	I MonoDroid:    at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue[] )
	I MonoDroid:    at Android.Runtime.InputStreamAdapter..ctor(Stream )
	I MonoDroid:    at Android.Runtime.InputStreamAdapter.ToLocalJniHandle(Stream )
	I MonoDroid:    at Android.Webkit.WebResourceResponse..ctor(String , String , Int32 , String , IDictionary`2 , Stream )
	I MonoDroid:    at Microsoft.AspNetCore.Components.WebView.Maui.WebKitWebViewClient.ShouldInterceptRequest(WebView view, IWebResourceRequest request)
	I MonoDroid:    at Android.Webkit.WebViewClient.n_ShouldInterceptRequest_Landroid_webkit_WebView_Landroid_webkit_WebResourceRequest_(IntPtr , IntPtr , IntPtr , IntPtr )
	I MonoDroid: 	at crc64d693e2d9159537db.WebKitWebViewClient.n_shouldInterceptRequest(Native Method)
	I MonoDroid: 	at crc64d693e2d9159537db.WebKitWebViewClient.shouldInterceptRequest(WebKitWebViewClient.java:39)
	I MonoDroid: 	at Rr.a(chromium-TrichromeWebViewGoogle.apk-stable-410410686:16)
	I MonoDroid: 	at org.chromium.android_webview.AwContentsBackgroundThreadClient.shouldInterceptRequestFromNative(chromium-TrichromeWebViewGoogle.apk-stable-410410686:2)
	I MonoDroid:
	I MonoDroid:   --- End of managed Android.Runtime.JavaProxyThrowable stack trace ---
	I MonoDroid: android.runtime.JavaProxyThrowable: System.ArgumentException: Arg_DlgtTargMeth
	I MonoDroid:    at System.Delegate.CreateDelegate(Type , Type , String , Boolean , Boolean )
	I MonoDroid:    at System.Delegate.CreateDelegate(Type , Type , String )
	I MonoDroid:    at Android.Runtime.AndroidTypeManager.RegisterNativeMembers(JniType , Type , String )
	I MonoDroid: --- End of stack trace from previous location ---
	I MonoDroid:    at Java.Interop.JniEnvironment.StaticMethods.CallStaticObjectMethod(JniObjectReference , JniMethodInfo , JniArgumentValue* )
	I MonoDroid:    at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue* )
	I MonoDroid:    at Android.Runtime.JNIEnv.CallStaticObjectMethod(IntPtr , IntPtr , JValue[] )
	I MonoDroid:    at Android.Runtime.JNIEnv.FindClass(String )
	I MonoDroid:    at Android.Runtime.JNIEnv.AllocObject(String )
	I MonoDroid:    at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue* )
	I MonoDroid:    at Android.Runtime.JNIEnv.StartCreateInstance(String , String , JValue[] )
	I MonoDroid:    at Android.Runtime.InputStreamAdapter..ctor(Stream )
	I MonoDroid:    at Android.Runtime.InputStreamAdapter.ToLocalJniHandle(Stream )
	I MonoDroid:    at Android.Webkit.WebResourceResponse..ctor(String , String , Int32 , String , IDictionary`2 , Stream )
	I MonoDroid:    at Microsoft.AspNetCore.Components.WebView.Maui.WebKitWebViewClient.ShouldInterceptRequest(WebView view, IWebResourceRequest request)
	I MonoDroid:    at Android.Webkit.WebViewClient.n_ShouldInterceptRequest_Landroid_webkit_WebView_Landroid_webkit_WebResourceRequest_(IntPtr , IntPtr , IntPtr , IntPtr )
	I MonoDroid: 	at crc64d693e2d9159537db.WebKitWebViewClient.n_shouldInterceptRequest(Native Method)
	I MonoDroid: 	at crc64d693e2d9159537db.WebKitWebViewClient.shouldInterceptRequest(WebKitWebViewClient.java:39)
	I MonoDroid: 	at Rr.a(chromium-TrichromeWebViewGoogle.apk-stable-410410686:16)
	I MonoDroid: 	at org.chromium.android_webview.AwContentsBackgroundThreadClient.shouldInterceptRequestFromNative(chromium-TrichromeWebViewGoogle.apk-stable-410410686:2)

This is much easier to reason about, and will save us time in
the future.

[0]: https://github.com/xamarin/xamarin-android/wiki/Blueprint#java-type-registration
dellis1972 pushed a commit that referenced this pull request May 26, 2022
Context: dotnet/install-scripts#15
Context: https://dot.net/v1/dotnet-install.sh
Context: https://dot.net/v1/dotnet-install.ps1

We've been installing dotnet versions using the [`dotnet-install`][0]
scripts for Unix & Windows.  However, they do not cache the
downloaded archive, and therefore we end up re-downloading the same
archive over and over again.

Additionally, if one finds themselves without an internet connection,
there's no way to easily install the required version of dotnet.

The installation scripts don't provide a way to cache the payloads
and they appear to be in maintenance mode (dotnet/install-scripts#15),
so there doesn't appear to be a chance to add caching support to them.

Fortunately, we can "ask" the scripts what they're downloading:

	% curl -o dotnet-install.sh 'https://dot.net/v1/dotnet-install.sh'
	% ./dotnet-install.sh --version 7.0.100-preview.5.22273.1 --verbose --dry-run  \
	| grep 'dotnet-install: URL'

This returns a list of URLs, which may or may not exist:

	dotnet-install: URL #0 - primary: https://dotnetcli.azureedge.net/dotnet/Sdk/7.0.100-preview.5.22273.1/dotnet-sdk-7.0.100-preview.5.22273.1-osx-x64.tar.gz
	dotnet-install: URL #1 - legacy: https://dotnetcli.azureedge.net/dotnet/Sdk/7.0.100-preview.5.22273.1/dotnet-dev-osx-x64.7.0.100-preview.5.22273.1.tar.gz
	dotnet-install: URL #2 - primary: https://dotnetbuilds.azureedge.net/public/Sdk/7.0.100-preview.5.22273.1/dotnet-sdk-7.0.100-preview.5.22273.1-osx-x64.tar.gz
	dotnet-install: URL #3 - legacy: https://dotnetbuilds.azureedge.net/public/Sdk/7.0.100-preview.5.22273.1/dotnet-dev-osx-x64.7.0.100-preview.5.22273.1.tar.gz

We now parse this output, extract the URLs, then download and cache
the URL contents into `$(AndroidToolchainCacheDirectory)`.

When we need to install .NET, we just extract the cached archive
into the appropriate directory.

If no `dotnet-install: URL…` messages are generated, then we run
the `dotnet-install` script as we previously did.

This process lets us take a first step towards fully "offline" builds,
along with smaller downloads on CI servers.

[0]: https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script
dellis1972 pushed a commit that referenced this pull request Jan 27, 2023
…otnet#7732)

Fixes: dotnet#7335

Context: d236af5

Commit d236af5 introduced embedded assembly compression, using LZ4,
which speeds up startup and reduces final package size.

Assemblies are compressed at build time and, at the same time, pre-
allocated buffers for the **decompressed** data are allocated in
`libxamarin-app.so`.  The buffers are then passed to the LZ4 APIs,
all threads using the same output buffer.  The assumption was that we
can do fine without locking as even if overlapped decompression
happens, the output data will be the same and so even if two threads
do the same thing at the same time, the data will be valid at all
times, so long as at least one thread completes the decompression.

This assumption proved to be **largely** true, but it appears that in
high concurrency cases it is possible that the data in the
decompression buffer differs.  This can result in app crashes:

	A/libc: Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 3092 (.NET ThreadPool), pid 2727 (myapp.name)
	A/DEBUG: pid: 2727, tid: 3092, name: .NET ThreadPool  >>> myapp.name <<<
	A/DEBUG:       #1 pc 0000000000029b1c  /data/app/myapp.name-B9t_3dF9i8mDxJEKodZw5w==/split_config.arm64_v8a.apk!libmono-android.release.so (offset 0x103d000) (xamarin::android::internal::MonodroidRuntime::mono_log_handler(char const*, char const*, char const*, int, void*)+144) (BuildId: 29c5a3805a0bedee1eede9b6668d7c676aa63371)
	A/DEBUG:       #2 pc 00000000002680bc  /data/app/myapp.name-B9t_3dF9i8mDxJEKodZw5w==/split_config.arm64_v8a.apk!libmonosgen-2.0.so (offset 0x109b000) (BuildId: 4a5dd4396e8816b7f69881838bd549285213d53b)
	A/DEBUG:       #3 pc 00000000002681e8  /data/app/myapp.name-B9t_3dF9i8mDxJEKodZw5w==/split_config.arm64_v8a.apk!libmonosgen-2.0.so (offset 0x109b000) (BuildId: 4a5dd4396e8816b7f69881838bd549285213d53b)
	A/DEBUG:       #4 pc 000000000008555c  /data/app/myapp.name-B9t_3dF9i8mDxJEKodZw5w==/split_config.arm64_v8a.apk!libmonosgen-2.0.so (offset 0x109b000) (mono_metadata_string_heap+188) (BuildId: 4a5dd4396e8816b7f69881838bd549285213d53b)
	…

My guess is that LZ4 either uses the output buffer as a scratchpad
area when decompressing or that it initializes/modifies the buffer
before writing actual data in it.  With overlapped decompression, it
may lead to one thread overwriting valid data previously written by
another thread, so that when the latter returns the buffer it thought
to have had valid data may contain certain bytes temporarily
overwritten by the decompression session in the other, still running,
thread.  It may happen that MonoVM reads the corrupted data just when
it is still invalid (before the still running decompression session
actually writes the valid data), a classic race condition.

To fix this, the decompression block is now protected with a startup-
aware mutex.  Mutex will be held only after the initial startup phase
is completed, so there should not be much loss of startup performance.
dellis1972 pushed a commit that referenced this pull request Feb 28, 2023
…otnet#7732)

Fixes: dotnet#7335

Context: d236af5

Commit d236af5 introduced embedded assembly compression, using LZ4,
which speeds up startup and reduces final package size.

Assemblies are compressed at build time and, at the same time, pre-
allocated buffers for the **decompressed** data are allocated in
`libxamarin-app.so`.  The buffers are then passed to the LZ4 APIs,
all threads using the same output buffer.  The assumption was that we
can do fine without locking as even if overlapped decompression
happens, the output data will be the same and so even if two threads
do the same thing at the same time, the data will be valid at all
times, so long as at least one thread completes the decompression.

This assumption proved to be **largely** true, but it appears that in
high concurrency cases it is possible that the data in the
decompression buffer differs.  This can result in app crashes:

	A/libc: Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 3092 (.NET ThreadPool), pid 2727 (myapp.name)
	A/DEBUG: pid: 2727, tid: 3092, name: .NET ThreadPool  >>> myapp.name <<<
	A/DEBUG:       #1 pc 0000000000029b1c  /data/app/myapp.name-B9t_3dF9i8mDxJEKodZw5w==/split_config.arm64_v8a.apk!libmono-android.release.so (offset 0x103d000) (xamarin::android::internal::MonodroidRuntime::mono_log_handler(char const*, char const*, char const*, int, void*)+144) (BuildId: 29c5a3805a0bedee1eede9b6668d7c676aa63371)
	A/DEBUG:       #2 pc 00000000002680bc  /data/app/myapp.name-B9t_3dF9i8mDxJEKodZw5w==/split_config.arm64_v8a.apk!libmonosgen-2.0.so (offset 0x109b000) (BuildId: 4a5dd4396e8816b7f69881838bd549285213d53b)
	A/DEBUG:       #3 pc 00000000002681e8  /data/app/myapp.name-B9t_3dF9i8mDxJEKodZw5w==/split_config.arm64_v8a.apk!libmonosgen-2.0.so (offset 0x109b000) (BuildId: 4a5dd4396e8816b7f69881838bd549285213d53b)
	A/DEBUG:       #4 pc 000000000008555c  /data/app/myapp.name-B9t_3dF9i8mDxJEKodZw5w==/split_config.arm64_v8a.apk!libmonosgen-2.0.so (offset 0x109b000) (mono_metadata_string_heap+188) (BuildId: 4a5dd4396e8816b7f69881838bd549285213d53b)
	…

My guess is that LZ4 either uses the output buffer as a scratchpad
area when decompressing or that it initializes/modifies the buffer
before writing actual data in it.  With overlapped decompression, it
may lead to one thread overwriting valid data previously written by
another thread, so that when the latter returns the buffer it thought
to have had valid data may contain certain bytes temporarily
overwritten by the decompression session in the other, still running,
thread.  It may happen that MonoVM reads the corrupted data just when
it is still invalid (before the still running decompression session
actually writes the valid data), a classic race condition.

To fix this, the decompression block is now protected with a startup-
aware mutex.  Mutex will be held only after the initial startup phase
is completed, so there should not be much loss of startup performance.
dellis1972 pushed a commit that referenced this pull request Jul 18, 2023
)

Context: 929e701
Context: ce2bc68
Context: dotnet#7473
Context: dotnet#8155

The managed linker can produce assemblies optimized for the target
`$(RuntimeIdentifier)` (RID), which means that they will differ
between different RIDs.  Our "favorite" example of this is
`IntPtr.Size`, which is inlined by the linker into `4` or `8` when
targeting 32-bit or 64-bit platforms.  (See also dotnet#7473 and 929e701.)

Another platform difference may come in the shape of CPU intrinsics
which will change the JIT-generated native code in ways that will
crash the application if the assembler instructions generated for the
intrinsics aren't supported by the underlying processor.

In addition, the per-RID assemblies will have different [MVID][0]s
and **may** have different type and method metadata token IDs, which
is important because typemaps *use* type and metadata token IDs; see
also ce2bc68.

All of this taken together invalidates our previous assumption that
all the managed assemblies are identical.  "Simply" using
`IntPtr.Size` in an assembly that contains `Java.Lang.Object`
subclasses will break things.

This in turn could cause "mysterious" behavior or crashes in Release
applications; see also Issue dotnet#8155.

Prevent the potential problems by processing each per-RID assembly
separately and output correct per-RID LLVM IR assembly using the
appropriate per-RID information.

Additionally, during testing I found that for our use of Cecil within
`<GenerateJavaStubs/>` doesn't consistently remove the fields,
delegates, and methods we remove in `MarshalMethodsAssemblyRewriter`
when marshal methods are enabled, or it generates subtly broken
assemblies which cause **some** applications to segfault at run time
like so:

	I monodroid-gc: 1 outstanding GREFs. Performing a full GC!
	F libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8 in tid 12379 (t6.helloandroid), pid 12379 (t6.helloandroid)
	F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
	F DEBUG   : Build fingerprint: 'google/raven_beta/raven:14/UPB3.230519.014/10284690:user/release-keys'
	F DEBUG   : Revision: 'MP1.0'
	F DEBUG   : ABI: 'arm64'
	F DEBUG   : Timestamp: 2023-07-04 22:09:58.762982002+0200
	F DEBUG   : Process uptime: 1s
	F DEBUG   : Cmdline: com.microsoft.net6.helloandroid
	F DEBUG   : pid: 12379, tid: 12379, name: t6.helloandroid  >>> com.microsoft.net6.helloandroid <<<
	F DEBUG   : uid: 10288
	F DEBUG   : tagged_addr_ctrl: 0000000000000001 (PR_TAGGED_ADDR_ENABLE)
	F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0000000000000008
	F DEBUG   : Cause: null pointer dereference
	F DEBUG   :     x0  0000000000000000  x1  0000007ba1401af0  x2  00000000000000fa  x3  0000000000000001
	F DEBUG   :     x4  0000007ba1401b38  x5  0000007b9f2a8360  x6  0000000000000000  x7  0000000000000000
	F DEBUG   :     x8  ffffffffffc00000  x9  0000007b9f800000  x10 0000000000000000  x11 0000007ba1400000
	F DEBUG   :     x12 0000000000000000  x13 0000007ba374ad58  x14 0000000000000000  x15 00000013ead77d66
	F DEBUG   :     x16 0000007ba372f210  x17 0000007ebdaa4a80  x18 0000007edf612000  x19 000000000000001f
	F DEBUG   :     x20 0000000000000000  x21 0000007b9f2a8320  x22 0000007b9fb02000  x23 0000000000000018
	F DEBUG   :     x24 0000007ba374ad08  x25 0000000000000004  x26 0000007b9f2a4618  x27 0000000000000000
	F DEBUG   :     x28 ffffffffffffffff  x29 0000007fc592a780
	F DEBUG   :     lr  0000007ba3701f44  sp  0000007fc592a730  pc  0000007ba3701e0c  pst 0000000080001000
	F DEBUG   : 8 total frames
	F DEBUG   : backtrace:
	F DEBUG   :       #00 pc 00000000002d4e0c  /data/app/~~Av24J15xbf20XdrY3X2_wA==/com.microsoft.net6.helloandroid-4DusuNWIAkz1Ssi7fWVF-g==/lib/arm64/libmonosgen-2.0.so (BuildId: 761134f2369377582cc3a8e25ecccb43a2e0a877)
	F DEBUG   :       #1 pc 00000000002c29e8  /data/app/~~Av24J15xbf20XdrY3X2_wA==/com.microsoft.net6.helloandroid-4DusuNWIAkz1Ssi7fWVF-g==/lib/arm64/libmonosgen-2.0.so (BuildId: 761134f2369377582cc3a8e25ecccb43a2e0a877)
	F DEBUG   :       #2 pc 00000000002c34bc  /data/app/~~Av24J15xbf20XdrY3X2_wA==/com.microsoft.net6.helloandroid-4DusuNWIAkz1Ssi7fWVF-g==/lib/arm64/libmonosgen-2.0.so (BuildId: 761134f2369377582cc3a8e25ecccb43a2e0a877)
	F DEBUG   :       #3 pc 00000000002c2254  /data/app/~~Av24J15xbf20XdrY3X2_wA==/com.microsoft.net6.helloandroid-4DusuNWIAkz1Ssi7fWVF-g==/lib/arm64/libmonosgen-2.0.so (BuildId: 761134f2369377582cc3a8e25ecccb43a2e0a877)
	F DEBUG   :       #4 pc 00000000002be0bc  /data/app/~~Av24J15xbf20XdrY3X2_wA==/com.microsoft.net6.helloandroid-4DusuNWIAkz1Ssi7fWVF-g==/lib/arm64/libmonosgen-2.0.so (BuildId: 761134f2369377582cc3a8e25ecccb43a2e0a877)
	F DEBUG   :       #5 pc 00000000002bf050  /data/app/~~Av24J15xbf20XdrY3X2_wA==/com.microsoft.net6.helloandroid-4DusuNWIAkz1Ssi7fWVF-g==/lib/arm64/libmonosgen-2.0.so (BuildId: 761134f2369377582cc3a8e25ecccb43a2e0a877)
	F DEBUG   :       #6 pc 00000000002a53a4  /data/app/~~Av24J15xbf20XdrY3X2_wA==/com.microsoft.net6.helloandroid-4DusuNWIAkz1Ssi7fWVF-g==/lib/arm64/libmonosgen-2.0.so (mono_gc_collect+44) (BuildId: 761134f2369377582cc3a8e25ecccb43a2e0a877)
	F DEBUG   :       #7 pc 000000000000513c  <anonymous:7ec716b000>

This is because we generate Java Callable Wrappers over a set of
original (linked or not) assemblies, then we scan them for classes
derived from `Java.Lang.Object` and use that set as input to the
marshal methods rewriter, which makes the changes (generates wrapper
methods, decorates wrapped methods with `[UnmanagedCallersOnly]`,
removes the old delegate methods as well as delegate backing fields)
to all the `Java.Lang.Object` subclasses, then writes the modified
assembly to a `new/<assembly.dll>` location (efa14e2), followed by
copying the newly written assemblies back to the original location.
At this point, we have the results returned by the subclass scanner
in memory and **new** versions of those types on disk, but they are
out of sync, since the types in memory refer to the **old** assemblies,
but AOT is ran on the **new** assemblies which have a different layout,
changed MVIDs and, potentially, different type and method token IDs
(because we added some methods, removed others etc) and thus it causes
the crashes at the run time.  The now invalid set of "old" types is
passed to the typemap generator.  This only worked by accident, because
we (incorrectly) used only the first linked assembly which happened
to be the same one passed to the JLO scanner and AOT - so everything
was fine at the execution time.

Address this by *disabling* LLVM Marshal Methods (8bc7a3e) for .NET 8,
setting `$(AndroidEnableMarshalMethods)`=False by default.
We'll attempt to fix these issues for .NET 9.

[0]: https://learn.microsoft.com/dotnet/api/system.reflection.module.moduleversionid?view=net-7.0
jonpryor pushed a commit that referenced this pull request Mar 20, 2024
)

Context: 5205a5f
Context: 8a5b2a0
Context: dotnet#8724
Context: dotnet#8797

As we have solved all trimming warnings (5205a5f. 8a5b2a0) in the
Android workload, we can now go "all in" on trimming.

Early in .NET 6 (maybe even 5?) we "hid" many trimming warnings as we
did not yet plan to solve them:

	<SuppressTrimAnalysisWarnings Condition=" '$(SuppressTrimAnalysisWarnings)' == '' ">true</SuppressTrimAnalysisWarnings>

These warnings were not *actionable* at the time for customers, as
many warnings were in `Mono.Android.dll`, `Java.Interop.dll`, etc.

Going forward, let's stop suppressing these warnings for
`$(TrimMode)`=full.

We can also enable trimming for new projects:

  * `dotnet new android`
  * `dotnet new android-wear`

New projects will have the [`$(TrimMode)`][0] property set to `Full`
by default:

	<!--
	  Enable full trimming in Release mode.
	  To learn more, see: https://learn.microsoft.com/dotnet/core/deploying/trimming/trimming-options#trimming-granularity
	-->
	<PropertyGroup Condition="'$(Configuration)' == 'Release'">
	  <TrimMode>full</TrimMode>
	</PropertyGroup>

We wouldn't want to do this for existing projects *yet*, as they
might have existing code, NuGet packages, etc. where trimming
warnings might be present.

We can also improve the templates for Android class libraries:

  * `dotnet new androidlib`
  * `dotnet new android-bindinglib`

New class library projects will have the [`$(IsTrimmable)`][1]
property set to `true` by default:

	<!--
	  Enable trim analyzers for Android class libraries.
	  To learn more, see: https://learn.microsoft.com/dotnet/core/deploying/trimming/prepare-libraries-for-trimming
	-->
	<IsTrimmable>true</IsTrimmable>

This way, new class libraries will be "trimmable" by default and be
able to react to trimming warnings.

We can also use `$(TrimMode)=full` in many of our existing tests:

  * MSBuild tests that assert 0 warnings can use `$(TrimMode)=full`.

  * On-device tests can use `$(TrimMode)=full`.


~~ General trimming warnings ~~

This was discovered through `Mono.Android-NET-Tests.csproj`, but
there were a few trimmer warnings in the "layout bindings" feature:

	…\dotnet\packs\Microsoft.Android.Sdk.Windows\…\tools\LayoutBinding.cs(79,56):
	  warning IL2091: Xamarin.Android.Design.LayoutBinding.<>c__DisplayClass8_0<T>.<FindFragment>b__0(Activity):
	  'T' generic argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors',
	    'DynamicallyAccessedMemberTypes.NonPublicConstructors' in 'Android.App.FragmentManager.FindFragmentById<T>(Int32)'.
	  The generic parameter 'T' of 'Xamarin.Android.Design.LayoutBinding.<>c__DisplayClass8_0<T>' does not have matching annotations.
	  The source value must declare at least the same requirements as those declared on the target location it is assigned to.
	…\dotnet\packs\Microsoft.Android.Sdk.Windows\…\tools\LayoutBinding.cs(35,5):
	  warning IL2091: Xamarin.Android.Design.LayoutBinding.FindView<T>(Int32, T&):
	  'T' generic argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors',
	    'DynamicallyAccessedMemberTypes.NonPublicConstructors' in 'Android.App.Activity.FindViewById<T>(Int32)'.
	  The generic parameter 'T' of 'Xamarin.Android.Design.LayoutBinding.FindView<T>(Int32, T&)' does not have matching annotations.
	  The source value must declare at least the same requirements as those declared on the target location it is assigned to.
	…\dotnet\packs\Microsoft.Android.Sdk.Windows\…\tools\LayoutBinding.cs(37,5):
	  warning IL2091: Xamarin.Android.Design.LayoutBinding.FindView<T>(Int32, T&):
	  'T' generic argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors',
	    'DynamicallyAccessedMemberTypes.NonPublicConstructors' in 'Android.Views.View.FindViewById<T>(Int32)'.
	  The generic parameter 'T' of 'Xamarin.Android.Design.LayoutBinding.FindView<T>(Int32, T&)' does not have matching annotations.
	  The source value must declare at least the same requirements as those declared on the target location it is assigned to.

We can `[DynamicallyAccessedMembers(Constructors)]` to fix these.


~~ Trimming warnings in tests ~~

Several tests that verify "trimming unsafe features" just specify:

	[RequiresUnreferencedCode ("Tests trimming unsafe features")]

If the test might have an issue under NativeAOT, I used:

	// FIXME: dotnet#8724
	#pragma warning disable IL3050

Places that use `Assembly.GetType()` can use `Type.GetType()` instead:

	-var JavaProxyThrowable_type = typeof (Java.Lang.Object)
	-    .Assembly
	-    .GetType ("Android.Runtime.JavaProxyThrowable");
	+var JavaProxyThrowable_type = Type.GetType ("Android.Runtime.JavaProxyThrowable, Mono.Android");

`SystemTests.AppDomainTest` was just ignored (and had warnings).
Update to just verify `PlatformNotSupportedException` is thrown.


~~ Test failures ~~

`JsonSerializerTest` requires setting
[`$(JsonSerializerIsReflectionEnabledByDefault)`][2]=true:

	<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>

Otherwise, an exception is thrown:

	System.InvalidOperationException : JsonSerializerIsReflectionDisabled

`Java.Interop-Tests` were initially not loaded at all, with the log
message:

	W NUnit   : Failed to load tests from assembly 'Java.Interop-Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065

If we make `Java.Interop-Tests.dll` a `@(TrimmerRootAssembly)`:

	<TrimmerRootAssembly Include="Java.Interop-Tests" RootMode="All" />

Then all the tests cases are preserved and can be run, in the same
way the "main app assembly" is preserved.

`Android.GraphicsTests.NinePatchTests` failed with:

	The drawable created from resource tile should be a NinePatchDrawable.
	Expected: not null
	But was:  null

The only usage of `NinePatchDrawable` was:

	Assert.IsNotNull (d as NinePatchDrawable);

`NinePatchDrawable` likely needs its interfaces and constructors
preserved for this test to pass.  I added an attribute for just `All`
members for the test to pass:

	[DynamicDependency (DynamicallyAccessedMemberTypes.All, typeof (NinePatchDrawable))]

`Xamarin.Android.RuntimeTests.CustomWidgetTests` failed with:

	(Binary XML file line #1 in Mono.Android.NET_Tests:layout/uppercase_custom: Binary XML file line #1 in Mono.Android.NET_Tests:layout/uppercase_custom: Error inflating class Mono.Android_Test.Library.CustomTextView)
	   at Java.Interop.JniEnvironment.InstanceMethods.CallObjectMethod(JniObjectReference , JniMethodInfo , JniArgumentValue* )
	   at Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualObjectMethod(String , IJavaPeerable , JniArgumentValue* )
	   at Android.Views.LayoutInflater.Inflate(Int32 , ViewGroup )
	   at Xamarin.Android.RuntimeTests.CustomWidgetTests.<>c.<UpperCaseCustomWidget_ShouldNotThrowInflateException>b__0_0()
	   at NUnit.Framework.Constraints.VoidInvocationDescriptor.Invoke()
	   at NUnit.Framework.Constraints.ExceptionInterceptor.Intercept(Object )
	--- End of managed Java.Lang.RuntimeException stack trace ---
	android.view.InflateException: Binary XML file line #1 in Mono.Android.NET_Tests:layout/uppercase_custom: Binary XML file line #1 in Mono.Android.NET_Tests:layout/uppercase_custom: Error inflating class Mono.Android_Test.Library.CustomTextView
	Caused by: android.view.InflateException: Binary XML file line #1 in Mono.Android.NET_Tests:layout/uppercase_custom: Error inflating class Mono.Android_Test.Library.CustomTextView
	Caused by: java.lang.ClassNotFoundException: Mono.Android_Test.Library.CustomTextView
	   at java.lang.Class.classForName(Native Method)
	   at java.lang.Class.forName(Class.java:454)
	   at android.view.LayoutInflater.createView(LayoutInflater.java:815)
	   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1006)
	   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:961)
	   at android.view.LayoutInflater.rInflate(LayoutInflater.java:1123)
	   at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1084)
	   at android.view.LayoutInflater.inflate(LayoutInflater.java:682)
	   at android.view.LayoutInflater.inflate(LayoutInflater.java:534)
	   at android.view.LayoutInflater.inflate(LayoutInflater.java:481)
	   at crc643df67da7b13bb6b1.TestInstrumentation_1.n_onStart(Native Method)
	   at crc643df67da7b13bb6b1.TestInstrumentation_1.onStart(TestInstrumentation_1.java:32)
	   at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2189)
	Caused by: java.lang.ClassNotFoundException: Didn't find class "Mono.Android_Test.Library.CustomTextView" on path

In this case, `Mono.Android_Test.Library.CustomTextView` was used
from an Android layout, but not used anywhere in managed code.

To fix, I added:

	[DynamicDependency (DynamicallyAccessedMemberTypes.All, typeof (Mono.Android_Test.Library.CustomTextView))]

I could have also made `Mono.Android_Test.Library` a `@(TrimmerRootAssembly)`.

TODO: `View` subclasses used within Android Layout `.axml` files
should be automatically preserved; see dotnet#8797.

[0]: https://learn.microsoft.com/dotnet/core/deploying/trimming/trimming-options?pivots=dotnet-8-0#trimming-granularity
[1]: https://learn.microsoft.com/dotnet/core/deploying/trimming/prepare-libraries-for-trimming?pivots=dotnet-8-0#enable-project-specific-trimming
[2]: https://learn.microsoft.com/dotnet/core/compatibility/serialization/8.0/publishtrimmed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant