Merge pull request #2763 from esdrubal/mono-symbolicate-standalone2
authorMarcos Henrich <marcoshenrich@gmail.com>
Wed, 30 Mar 2016 07:55:15 +0000 (08:55 +0100)
committerMarcos Henrich <marcoshenrich@gmail.com>
Wed, 30 Mar 2016 07:55:15 +0000 (08:55 +0100)
Mono-symbolicate standalone

mcs/class/corlib/System.Diagnostics/StackFrame.cs
mcs/class/corlib/System.Diagnostics/StackTrace.cs
mcs/class/corlib/System.Diagnostics/StackTraceHelper.cs [new file with mode: 0644]
mcs/class/corlib/corlib.dll.sources
mcs/tools/mono-symbolicate/LocationProvider.cs
mcs/tools/mono-symbolicate/SeqPointInfo.cs [new file with mode: 0644]
mcs/tools/mono-symbolicate/mono-symbolicate.exe.sources
mono/metadata/icall-def.h
mono/metadata/icall.c

index 2593f96c68d372382cf6f37764c29f9966fe58bf..702cd540d976d92e34dbce66fc2e116a679f2603 100644 (file)
@@ -60,9 +60,6 @@ namespace System.Diagnostics {
                #pragma warning restore 649
                #endregion
 
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               extern static int GetILOffsetFromFile (string path, int methodToken, uint methodIndex, int nativeOffset);
-
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                extern static bool get_frame_info (int skip, bool needFileInfo, out MethodBase method,
                                                   out int iloffset, out int native_offset,
index 4c322cd107fc95a732c4763db1ffb5bd675d57c9..afa470dd5c3dbd1c4e500fec031ee5805e549959 100644 (file)
@@ -201,7 +201,7 @@ namespace System.Diagnostics {
                                        else
                                                sb.AppendFormat ("<0x{0:x5} + 0x{1:x5}> {2}", frame.GetMethodAddress (), frame.GetNativeOffset (), unknown);
                                } else {
-                                       GetFullNameForStackTrace (sb, frame.GetMethod ());
+                                       StackTraceHelper.GetFullNameForStackTrace (sb, frame.GetMethod ());
 
                                        if (frame.GetILOffset () == -1) {
                                                sb.AppendFormat (" <0x{0:x5} + 0x{1:x5}>", frame.GetMethodAddress (), frame.GetNativeOffset ());
@@ -219,64 +219,6 @@ namespace System.Diagnostics {
                        return i != 0;
                }
 
-               // This method is also used with reflection by mono-symbolicate tool.
-               // mono-symbolicate tool uses this method to check which method matches
-               // the stack frame method signature.
-               static void GetFullNameForStackTrace (StringBuilder sb, MethodBase mi)
-               {
-                       var declaringType = mi.DeclaringType;
-                       if (declaringType.IsGenericType && !declaringType.IsGenericTypeDefinition)
-                               declaringType = declaringType.GetGenericTypeDefinition ();
-
-                       // Get generic definition
-                       var bindingflags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
-                       foreach (var m in declaringType.GetMethods (bindingflags)) {
-                               if (m.MetadataToken == mi.MetadataToken) {
-                                       mi = m;
-                                       break;
-                               }
-                       }
-
-                       sb.Append (declaringType.ToString ());
-
-                       sb.Append (".");
-                       sb.Append (mi.Name);
-
-                       if (mi.IsGenericMethod) {
-                               Type[] gen_params = mi.GetGenericArguments ();
-                               sb.Append ("[");
-                               for (int j = 0; j < gen_params.Length; j++) {
-                                       if (j > 0)
-                                               sb.Append (",");
-                                       sb.Append (gen_params [j].Name);
-                               }
-                               sb.Append ("]");
-                       }
-
-                       ParameterInfo[] p = mi.GetParametersInternal ();
-
-                       sb.Append (" (");
-                       for (int i = 0; i < p.Length; ++i) {
-                               if (i > 0)
-                                       sb.Append (", ");
-
-                               Type pt = p[i].ParameterType;
-                               if (pt.IsGenericType && ! pt.IsGenericTypeDefinition)
-                                       pt = pt.GetGenericTypeDefinition ();
-
-                               if (pt.IsClass && !String.IsNullOrEmpty (pt.Namespace)) {
-                                       sb.Append (pt.Namespace);
-                                       sb.Append (".");
-                               }
-                               sb.Append (pt.Name);
-                               if (p [i].Name != null) {
-                                       sb.Append (" ");
-                                       sb.Append (p [i].Name);
-                               }
-                       }
-                       sb.Append (")");
-               }
-
                public override string ToString ()
                {
                        StringBuilder sb = new StringBuilder ();
diff --git a/mcs/class/corlib/System.Diagnostics/StackTraceHelper.cs b/mcs/class/corlib/System.Diagnostics/StackTraceHelper.cs
new file mode 100644 (file)
index 0000000..3bf9995
--- /dev/null
@@ -0,0 +1,92 @@
+//
+// System.Diagnostics.StackTraceHelper.cs
+//
+// Author:
+//      Marcos Henrich (marcos.henrich@xamarin.com)
+//
+// Copyright (C) Xamarin, Inc (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Text;
+using System.Reflection;
+
+namespace System.Diagnostics {
+
+       // This class exists so tools such as mono-symbolicate can use it directly.
+       class StackTraceHelper {
+               
+               public static void GetFullNameForStackTrace (StringBuilder sb, MethodBase mi)
+               {
+                       var declaringType = mi.DeclaringType;
+                       if (declaringType.IsGenericType && !declaringType.IsGenericTypeDefinition)
+                               declaringType = declaringType.GetGenericTypeDefinition ();
+
+                       // Get generic definition
+                       var bindingflags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
+                       foreach (var m in declaringType.GetMethods (bindingflags)) {
+                               if (m.MetadataToken == mi.MetadataToken) {
+                                       mi = m;
+                                       break;
+                               }
+                       }
+
+                       sb.Append (declaringType.ToString ());
+
+                       sb.Append (".");
+                       sb.Append (mi.Name);
+
+                       if (mi.IsGenericMethod) {
+                               Type[] gen_params = mi.GetGenericArguments ();
+                               sb.Append ("[");
+                               for (int j = 0; j < gen_params.Length; j++) {
+                                       if (j > 0)
+                                               sb.Append (",");
+                                       sb.Append (gen_params [j].Name);
+                               }
+                               sb.Append ("]");
+                       }
+
+                       ParameterInfo[] p = mi.GetParameters ();
+
+                       sb.Append (" (");
+                       for (int i = 0; i < p.Length; ++i) {
+                               if (i > 0)
+                                       sb.Append (", ");
+
+                               Type pt = p[i].ParameterType;
+                               if (pt.IsGenericType && ! pt.IsGenericTypeDefinition)
+                                       pt = pt.GetGenericTypeDefinition ();
+
+                               if (pt.IsClass && !String.IsNullOrEmpty (pt.Namespace)) {
+                                       sb.Append (pt.Namespace);
+                                       sb.Append (".");
+                               }
+                               sb.Append (pt.Name);
+                               if (p [i].Name != null) {
+                                       sb.Append (" ");
+                                       sb.Append (p [i].Name);
+                               }
+                       }
+                       sb.Append (")");
+               }
+       }
+}
index 35ed33617c26884fa55a28c2d058cfb533a30179..9a2b075df8837573163a5a1b72119eb1210281a2 100644 (file)
@@ -161,6 +161,7 @@ System.Deployment.Internal/InternalApplicationIdentityHelper.cs
 System.Diagnostics/Debugger.cs
 System.Diagnostics/StackFrame.cs
 System.Diagnostics/StackTrace.cs
+System.Diagnostics/StackTraceHelper.cs
 System.Diagnostics.Tracing/EventAttribute.cs
 System.Diagnostics.Tracing/EventCommand.cs
 System.Diagnostics.Tracing/EventSource.cs
index 2fc8018c7b492d35bf26e46193ca5acadfc1d5b7..0580eeb9615db86aba1c056ff7e1256b528423e6 100644 (file)
@@ -7,6 +7,7 @@ using System.Diagnostics;
 using System.Collections.Generic;
 using Mono.Cecil;
 using Mono.CompilerServices.SymbolWriter;
+using System.Runtime.InteropServices;
 
 namespace Symbolicate
 {
@@ -57,33 +58,20 @@ namespace Symbolicate
                                return true;
                        }
 
-                       static MethodInfo methodGetIL;
+                       SeqPointInfo seqPointInfo;
                        private int GetILOffsetFromFile (int methodToken, uint methodIndex, int nativeOffset)
                        {
-                               if (string.IsNullOrEmpty (seqPointDataPath))
-                                       return -1;
+                               if (seqPointInfo == null)
+                                       seqPointInfo = SeqPointInfo.Read (seqPointDataPath);
 
-                               if (methodGetIL == null)
-                                       methodGetIL = typeof (StackFrame).GetMethod ("GetILOffsetFromFile", BindingFlags.NonPublic | BindingFlags.Static);
-
-                               if (methodGetIL == null)
-                                       throw new Exception ("System.Diagnostics.StackFrame.GetILOffsetFromFile could not be found, make sure you have an updated mono installed.");
-
-                               return (int) methodGetIL.Invoke (null, new object[] {seqPointDataPath, methodToken, methodIndex, nativeOffset});
+                               return seqPointInfo.GetILOffset (methodToken, methodIndex, nativeOffset);
                        }
 
-                       static MethodInfo methodGetMethodFullName;
                        private string GetMethodFullName (MethodBase m)
                        {
-
-                               if (methodGetMethodFullName == null)
-                                       methodGetMethodFullName = typeof (StackTrace).GetMethod ("GetFullNameForStackTrace", BindingFlags.NonPublic | BindingFlags.Static);
-
-                               if (methodGetMethodFullName == null)
-                                       throw new Exception ("System.Exception.GetFullNameForStackTrace could not be found, make sure you have an updated mono installed.");
-
                                StringBuilder sb = new StringBuilder ();
-                               methodGetMethodFullName.Invoke (null, new object[] {sb, m});
+
+                               StackTraceHelper.GetFullNameForStackTrace (sb, m);
 
                                return sb.ToString ();
                        }
@@ -106,7 +94,7 @@ namespace Symbolicate
                        if (!File.Exists (assemblyPath))
                                throw new ArgumentException ("assemblyPath does not exist: "+ assemblyPath);
 
-                       var assembly = Assembly.LoadFrom (assemblyPath);
+                       var assembly = Assembly.ReflectionOnlyLoadFrom (assemblyPath);
                        MonoSymbolFile symbolFile = null;
 
                        var symbolPath = assemblyPath + ".mdb";
diff --git a/mcs/tools/mono-symbolicate/SeqPointInfo.cs b/mcs/tools/mono-symbolicate/SeqPointInfo.cs
new file mode 100644 (file)
index 0000000..606e4fb
--- /dev/null
@@ -0,0 +1,156 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+
+namespace Symbolicate
+{
+       static class BinaryReaderExtensions
+       {
+               public static int ReadVariableInt (this BinaryReader reader)
+               {
+                       int val = 0;
+                       for (var i = 0; i < 4; i++) {
+                               var b = reader.ReadByte ();
+                               val |= (b & 0x7f) << (7 * i);
+                               if ((b & 0x80) == 0)
+                                       return val;
+                       }
+
+                       throw new Exception ("Invalid variable int");
+               }
+
+               public static int ReadVariableZigZagInt (this BinaryReader reader)
+               {
+                       int enc = ReadVariableInt (reader);
+                       int val = enc >> 1;
+                       return ((enc & 1) == 0)? val : -val;
+               }
+       }
+
+       class SeqPointInfo
+       {
+               class MethodData
+               {
+                       List<SeqPoint> seqPoints;
+
+                       public static MethodData Read (BinaryReader reader)
+                       {
+                               var hasDebugData = reader.ReadVariableInt () != 0;
+                               var dataSize = reader.ReadVariableInt ();
+                               var dataEnd = reader.BaseStream.Position + dataSize;
+
+                               var seqPoints = new List<SeqPoint> ();
+                               SeqPoint prev = null;
+                               while (reader.BaseStream.Position < dataEnd) {
+                                       var seqPoint = SeqPoint.Read (reader, prev, hasDebugData);
+                                       seqPoints.Add (seqPoint);
+                                       prev = seqPoint;
+                               }
+
+                               if (reader.BaseStream.Position != dataEnd)
+                                       throw new Exception ("Read more seq point than expected.");
+
+                               return new MethodData () { seqPoints = seqPoints };
+                       }
+
+                       public bool TryGetILOffset (int nativeOffset, out int ilOffset)
+                       {
+                               ilOffset = 0;
+                               SeqPoint prev = null;
+                               foreach (var seqPoint in seqPoints) {
+                                       if (seqPoint.NativeOffset > nativeOffset)
+                                               break;
+                                       prev = seqPoint;
+                               }
+
+                               if (prev == null)
+                                       return false;
+
+                               ilOffset = prev.ILOffset;
+                               return true;
+                       }
+               }
+
+               class SeqPoint
+               {
+                       public readonly int ILOffset;
+                       public readonly int NativeOffset;
+
+                       public SeqPoint (int ilOffset, int nativeOffset)
+                       {
+                               ILOffset = ilOffset;
+                               NativeOffset = nativeOffset;
+                       }
+
+                       public static SeqPoint Read (BinaryReader reader, SeqPoint prev, bool hasDebug)
+                       {
+                               var ilOffset = reader.ReadVariableZigZagInt ();
+                               var nativeOffset = reader.ReadVariableZigZagInt ();
+
+                               // Respect delta encoding
+                               if (prev != null) {
+                                       ilOffset += prev.ILOffset;
+                                       nativeOffset += prev.NativeOffset;
+                               }
+
+                               //Read everything to ensure the buffer position is at the end of the seq point data.
+                               if (hasDebug) {
+                                       reader.ReadVariableInt (); // flags
+
+                                       var next_length = reader.ReadVariableInt ();
+                                       for (var i = 0; i < next_length; ++i)
+                                               reader.ReadVariableInt ();
+                               }
+
+                               return new SeqPoint (ilOffset, nativeOffset);
+                       }
+               };
+
+               Dictionary<Tuple<int,int>, MethodData> dataByIds;
+               Dictionary<int, MethodData> dataByTokens;
+
+               public static SeqPointInfo Read (string path)
+               {
+                       using (var reader = new BinaryReader (File.Open (path, FileMode.Open)))
+                       {
+                               var dataByIds = new Dictionary<Tuple<int,int>, MethodData> ();
+                               var dataByTokens = new Dictionary<int, MethodData> ();
+
+                               var methodCount = reader.ReadVariableInt ();
+
+                               for (var i = 0; i < methodCount; ++i) {
+                                       var methodToken = reader.ReadVariableInt ();
+                                       var methodIndex = reader.ReadVariableInt ();
+                                       var methodId = new Tuple<int, int> (methodToken, methodIndex);
+
+                                       var methodData = MethodData.Read (reader);
+
+                                       dataByIds.Add (methodId, methodData);
+                                       if (!dataByTokens.ContainsKey (methodToken))
+                                               dataByTokens.Add (methodToken, methodData);
+                               }
+
+                               return new SeqPointInfo { dataByIds  = dataByIds, dataByTokens = dataByTokens };
+                       }
+               }
+
+               public int GetILOffset (int methodToken, uint methodIndex, int nativeOffset)
+               {
+                       MethodData methodData;
+                       if (methodIndex == 0xffffff) {
+                          if (!dataByTokens.TryGetValue (methodToken, out methodData))
+                                       throw new Exception (string.Format ("Could not find data for method token {0:X}", methodToken));
+                       } else {
+                               var methodId = new Tuple<int, int> (methodToken, (int)methodIndex);
+                               if (!dataByIds.TryGetValue (methodId, out methodData))
+                                       throw new Exception (string.Format ("Could not find data for method token {0:X} with index {1:X}", methodToken, methodIndex));
+                       }
+
+                       int ilOffset;
+                       if (!methodData.TryGetILOffset (nativeOffset, out ilOffset))
+                               throw new Exception ("Could not retrieve IL offset");
+
+                       return ilOffset;
+               }
+       }
+}
index 968d028d0e95a50ac0f9a060963714a545036a7b..7f50e887c2032b2fde8f5f62f689241af91c5237 100644 (file)
@@ -1,2 +1,4 @@
 symbolicate.cs
-LocationProvider.cs
\ No newline at end of file
+LocationProvider.cs
+SeqPointInfo.cs
+../../class/corlib/System.Diagnostics/StackTraceHelper.cs
index b8a9cd97a80f46892e8128e4095bd79a7d749337..5ca728a0489c0ee158e1279b326d7646411a1c5c 100644 (file)
@@ -210,9 +210,6 @@ ICALL(PROCESS_10, "ProcessName_internal(intptr)", ves_icall_System_Diagnostics_P
 ICALL(PROCESS_13, "ShellExecuteEx_internal(System.Diagnostics.ProcessStartInfo,System.Diagnostics.Process/ProcInfo&)", ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal)
 #endif /* !DISABLE_PROCESS_HANDLING */
 
-ICALL_TYPE(SFRAME, "System.Diagnostics.StackFrame", SFRAME_1)
-ICALL(SFRAME_1, "GetILOffsetFromFile", ves_icall_System_StackFrame_GetILOffsetFromFile)
-
 ICALL_TYPE(STOPWATCH, "System.Diagnostics.Stopwatch", STOPWATCH_1)
 ICALL(STOPWATCH_1, "GetTimestamp", mono_100ns_ticks)
 
index 7b2d955ce7783cf5ce9bea727fe3005ff92286f8..01be8d10162465eebda5aec982653fd6c1f7bc8e 100644 (file)
@@ -8022,20 +8022,6 @@ ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
        return message;
 }
 
-ICALL_EXPORT int
-ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
-{
-       guint32 il_offset;
-       char *path_str = mono_string_to_utf8 (path);
-
-       if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
-               il_offset = -1;
-
-       g_free (path_str);
-
-       return il_offset;
-}
-
 ICALL_EXPORT gpointer
 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
 {