Bug 16898 - GetAssembly returns null CustomAttributes on Android and iOS when it should be returning information. Expecting to find DebuggableAttribute.
Summary: GetAssembly returns null CustomAttributes on Android and iOS when it should b...
Status: RESOLVED FIXED
Alias: None
Product: Class Libraries
Classification: Mono
Component: mscorlib ()
Version: master
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on: 16924
Blocks:
  Show dependency tree
 
Reported: 2013-12-19 12:45 UTC by Stephen Rawlins
Modified: 2014-01-06 12:47 UTC (History)
5 users (show)

Tags: mscorlib,pcl,getassembly
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Stephen Rawlins 2013-12-19 12:45:28 UTC
We are trying to determine if an assembly is Debug or Production using Assembly.GetAssembly(typeof(iApp));

The code works on Microsoft Windows, but not on Xamarin's mscorlib 

On Xamarin/iOS mscorblib, GetAssembly returns 11 null CustomAttributes
On Xamarin/Android mscorlib, same call returns 13 null CustomAttributes

On Windows, the same call returns 13 non-null CustomAttributes, including the Debugging Attribute we depend upon to determine whether or not the target assembly is Debug-build.

      public static bool IsReleaseBuild()  
        {
            Assembly assm = Assembly.GetAssembly(typeof(iApp));  //  iApp is in the Assembly in question
            object[] attributes = assm.GetCustomAttributes(typeof(DebuggableAttribute), false);

            // The Assembly is assumed to be a Release Build (vs. Debug) if there are no attributes at all, or if the
            // attributes carry no debug
            bool isRelease = true;
            if (attributes.Length > 0)
            {
                foreach (Attribute attr in attributes)
                {
                    if (isRelease && attr is DebuggableAttribute)
                    {
                        DebuggableAttribute d = attr as DebuggableAttribute;
                        System.Diagnostics.Debug.WriteLine(
                           String.Format("Run time Optimizer is enabled : {0}", !d.IsJITOptimizerDisabled));
                        System.Diagnostics.Debug.WriteLine(
                            String.Format("Run time Tracking is enabled : {0}", d.IsJITTrackingEnabled));
                        if (d.IsJITOptimizerDisabled == true)  // If Optimization turned off, call it a Debug build and quit.
                        {
                            System.Diagnostics.Debug.WriteLine(String.Format("{0} is a DEBUG Build....", assm.FullName));
                            isRelease = false;
                        }
                        else   // if Optimized code, then keep looping, but still assume it's a Relase build
                        {
                            System.Diagnostics.Debug.WriteLine(String.Format("{0} is a RELEASE Build....", assm.FullName));
                        }
                    }
                }
            }
            return isRelease;
        }
Comment 1 Stephen Rawlins 2013-12-19 13:54:07 UTC
Here is debug from Xamarin Studio, showing the CustomAttributes (Count=11).  All 11 were null.

{iFactr.UI, Version=3.4.0.42, Culture=neutral, PublicKeyToken=null}
	CodeBase: "file:///Users/ifactr/Library/Application Support/iPhone Simulator/7.0.3/Applications/FCF74405-7943-4F06-9E8E-723870FA7141/TestRunnerTouch.app/iFactr.UI.dll"
	CustomAttributes: Count=11
	DefinedTypes: {System.Reflection.Assembly}
	EntryPoint: (null)
	EscapedCodeBase: "file:///Users/ifactr/Library/Application%20Support/iPhone%20Simulator/7.0.3/Applications/FCF74405-7943-4F06-9E8E-723870FA7141/TestRunnerTouch.app/iFactr.UI.dll"
	Evidence: (null)
	ExportedTypes: {System.MonoType[136]}
	FullName: "iFactr.UI, Version=3.4.0.42, Culture=neutral, PublicKeyToken=null"
	GlobalAssemblyCache (System.Reflection.MonoAssembly): false
	System.NotImplementedException: Derived classes must implement it
	HostContext: 0
	ImageRuntimeVersion: "v4.0.30319"
	IsDynamic: false
	IsFullyTrusted: true
	Location: "/Users/ifactr/Library/Application Support/iPhone Simulator/7.0.3/Applications/FCF74405-7943-4F06-9E8E-723870FA7141/TestRunnerTouch.app/iFactr.UI.dll"
	ManifestModule (System.Reflection.MonoAssembly): {iFactr.UI.dll}
	System.NotImplementedException: Derived classes must implement it
	Modules: {System.Reflection.Module[1]}
	ReflectionOnly: false
	Non-public members:
Comment 2 Stephen Rawlins 2013-12-19 14:02:39 UTC
MSWindows, in contrast, returns the following from GetAssembly:

assm
{iFactr.UI, Version=3.4.0.42, Culture=neutral, PublicKeyToken=null}
    [System.Reflection.RuntimeAssembly]: {iFactr.UI, Version=3.4.0.42, Culture=neutral, PublicKeyToken=null}
    CodeBase: "file:///Z:/Projects/iFactr_Trunk_Repo/QA/Core.UnitTests/bin/Debug/iFactr.UI.DLL"
    CustomAttributes: Count = 13
    DefinedTypes: {System.RuntimeType[157]}
    EntryPoint: null
    EscapedCodeBase: "file:///Z:/Projects/iFactr_Trunk_Repo/QA/Core.UnitTests/bin/Debug/iFactr.UI.DLL"
    Evidence: {System.Security.Policy.Evidence}
    ExportedTypes: {System.Type[136]}
    FullName: "iFactr.UI, Version=3.4.0.42, Culture=neutral, PublicKeyToken=null"
    GlobalAssemblyCache: false
    HostContext: 0
    ImageRuntimeVersion: "v4.0.30319"
    IsDynamic: false
    IsFullyTrusted: true
    Location: "Z:\\Projects\\iFactr_Trunk_Repo\\QA\\Core.UnitTests\\bin\\Debug\\iFactr.UI.dll"
    ManifestModule: {iFactr.UI.dll}
    Modules: {System.Reflection.RuntimeModule[1]}
    PermissionSet: {<PermissionSet class="System.Security.PermissionSet"
version="1"
Unrestricted="true"/>
}
    ReflectionOnly: false
    SecurityRuleSet: Level2



Here is the DebuggableAttribute (for example), showing its actionable content:


attributes
{System.Diagnostics.DebuggableAttribute[1]}
    [0]: {System.Diagnostics.DebuggableAttribute}
attributes[0]
{System.Diagnostics.DebuggableAttribute}
    base: {System.Diagnostics.DebuggableAttribute}
    DebuggingFlags: Default | DisableOptimizations | IgnoreSymbolStoreSequencePoints | EnableEditAndContinue
    IsJITOptimizerDisabled: true
    IsJITTrackingEnabled: true
Comment 3 Jonathan Pryor 2013-12-20 09:36:59 UTC
What link mode do you have enabled, Link SDK Assemblies or Link All Assemblies?

The linker always removes the following attributes from linked assemblies:

	System.ObsoleteAttribute
	System.MonoDocumentationNoteAttribute
	System.MonoExtensionAttribute
	System.MonoInternalNoteAttribute
	System.MonoLimitationAttribute
	System.MonoNotSupportedAttribute
	System.MonoTODOAttribute
	System.Xml.MonoFIXAttribute

The linker will remove the following attributes from linked assemblies in Release builds, but preserve them for Debug builds:

	System.Diagnostics.DebuggableAttribute
	System.Diagnostics.DebuggerBrowsableAttribute
	System.Diagnostics.DebuggerDisplayAttribute
	System.Diagnostics.DebuggerHiddenAttribute
	System.Diagnostics.DebuggerNonUserCodeAttribute
	System.Diagnostics.DebuggerStepperBoundaryAttribute
	System.Diagnostics.DebuggerStepThroughAttribute
	System.Diagnostics.DebuggerTypeProxyAttribute
	System.Diagnostics.DebuggerVisualizerAttribute

I would expect these attributes to be preserved in your application assemblies if you're using Link SDK Assemblies. If you're using Link All Assemblies, I would expect these attributes to be removed in Release builds.
Comment 4 Stephen Rawlins 2013-12-20 10:37:34 UTC
For the main programmer on our iOS/Touch app (TestRunner.Touch) the Options/iOS Build/Linker Options
/Linker Behavior is "Don't Link"
Comment 5 Rolf Bjarne Kvinge [MSFT] 2013-12-20 18:39:33 UTC
The problem seems to be that mcs does not add DebuggableAttribute to any assemblies.
Comment 6 Rolf Bjarne Kvinge [MSFT] 2014-01-06 11:51:23 UTC
mcs has now been fixed, so this should work once Mono 3.2.7 is released (note in particular that 3.2.6 will not have this fix).
Comment 7 Stephen Rawlins 2014-01-06 12:47:52 UTC
Thank you very much for your quick attention to this issue. I appreciate it.