#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,
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 ());
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 ();
--- /dev/null
+//
+// 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 (")");
+ }
+ }
+}
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
using System.Collections.Generic;
using Mono.Cecil;
using Mono.CompilerServices.SymbolWriter;
+using System.Runtime.InteropServices;
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 ();
}
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";
--- /dev/null
+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;
+ }
+ }
+}
symbolicate.cs
-LocationProvider.cs
\ No newline at end of file
+LocationProvider.cs
+SeqPointInfo.cs
+../../class/corlib/System.Diagnostics/StackTraceHelper.cs
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)
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)
{