Improved generics in exception's stack traces and mono-symbolicate.
private int ilOffset = OFFSET_UNKNOWN;
private int nativeOffset = OFFSET_UNKNOWN;
private long methodAddress;
+ private uint methodIndex;
private MethodBase methodBase;
private string fileName;
private int lineNumber;
#endregion
[MethodImplAttribute (MethodImplOptions.InternalCall)]
- extern static int GetILOffsetFromFile (string path, int methodToken, int nativeOffset);
+ 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,
return methodAddress;
}
+ internal uint GetMethodIndex ()
+ {
+ return methodIndex;
+ }
+
internal string GetInternalMethodName ()
{
return internalMethodName;
* of icalls, do not require an increment.
*/
#pragma warning disable 169
- private const int mono_corlib_version = 123;
+ private const int mono_corlib_version = 124;
#pragma warning restore 169
[ComVisible (true)]
} else {
GetFullNameForStackTrace (sb, frame.GetMethod ());
- if (frame.GetILOffset () == -1)
- sb.AppendFormat ("<0x{0:x5} + 0x{1:x5}> ", frame.GetMethodAddress (), frame.GetNativeOffset ());
- else
+ if (frame.GetILOffset () == -1) {
+ sb.AppendFormat (" <0x{0:x5} + 0x{1:x5}> ", frame.GetMethodAddress (), frame.GetNativeOffset ());
+ if (frame.GetMethodIndex () != 0xffffff)
+ sb.AppendFormat ("{0} ", frame.GetMethodIndex ());
+ } else {
sb.AppendFormat (" [0x{0:x5}] ", frame.GetILOffset ());
+ }
sb.AppendFormat ("in {0}:{1} ", frame.GetSecureFileName (),
frame.GetFileLineNumber ());
return this;
}
- internal void GetFullNameForStackTrace (StringBuilder sb, MethodBase mi)
+ internal static void GetFullNameForStackTrace (StringBuilder sb, MethodBase mi)
{
- ParameterInfo[] p = mi.GetParametersInternal ();
- sb.Append (mi.DeclaringType.ToString ());
+ 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);
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 (".");
using System;
using System.IO;
using System.Linq;
+using System.Text;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Generic;
class LocationProvider {
class AssemblyLocationProvider {
- AssemblyDefinition assembly;
+ Assembly assembly;
MonoSymbolFile symbolFile;
string seqPointDataPath;
- public AssemblyLocationProvider (AssemblyDefinition assembly, MonoSymbolFile symbolFile, string seqPointDataPath)
+ public AssemblyLocationProvider (Assembly assembly, MonoSymbolFile symbolFile, string seqPointDataPath)
{
this.assembly = assembly;
this.symbolFile = symbolFile;
this.seqPointDataPath = seqPointDataPath;
}
- public bool TryGetLocation (string methodFullName, string[] methodParamsTypes, int offset, bool isOffsetIL, out Location location)
+ public bool TryGetLocation (string methodStr, string typeFullName, int offset, bool isOffsetIL, uint methodIndex, out Location location)
{
location = default (Location);
if (symbolFile == null)
return false;
- var typeNameEnd = methodFullName.LastIndexOf (".");
- var typeName = methodFullName.Substring (0, typeNameEnd);
- var methodName = methodFullName.Substring (typeNameEnd + 1, methodFullName.Length - typeNameEnd - 1);
-
- var type = assembly.MainModule.Types.FirstOrDefault (t => t.FullName == typeName);
+ var type = assembly.GetTypes().FirstOrDefault (t => t.FullName == typeFullName);
if (type == null)
return false;
- var method = type.Methods.FirstOrDefault (m => {
- if (m.Name != methodName)
- return false;
-
- if (m.Parameters.Count != methodParamsTypes.Length)
- return false;
-
- for (var i = 0; i < methodParamsTypes.Length; i++) {
- var paramType = m.Parameters[i].ParameterType;
- if (paramType.Name != methodParamsTypes[i])
- return false;
- }
-
- return true;
- });
-
+ var bindingflags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
+ var method = type.GetMethods(bindingflags).FirstOrDefault (m => GetMethodFullName (m) == methodStr);
if (method == null)
return false;
- int ilOffset = (isOffsetIL)? offset : GetILOffsetFromFile (method.MetadataToken.ToInt32 (), offset);
+ int ilOffset = (isOffsetIL)? offset : GetILOffsetFromFile (method.MetadataToken, methodIndex, offset);
if (ilOffset < 0)
return false;
- var methodSymbol = symbolFile.Methods [method.MetadataToken.RID-1];
+ var methodSymbol = symbolFile.Methods [(method.MetadataToken & 0x00ffffff) - 1];
- foreach (var lineNumber in methodSymbol.GetLineNumberTable ().LineNumbers) {
- if (lineNumber.Offset < ilOffset)
- continue;
-
- location.FileName = symbolFile.Sources [lineNumber.File-1].FileName;
- location.Line = lineNumber.Row;
- return true;
- }
+ var lineNumbers = methodSymbol.GetLineNumberTable ().LineNumbers;
+ var lineNumber = lineNumbers.FirstOrDefault (l => l.Offset >= ilOffset) ?? lineNumbers.Last ();
- return false;
+ location.FileName = symbolFile.Sources [lineNumber.File-1].FileName;
+ location.Line = lineNumber.Row;
+ return true;
}
static MethodInfo methodGetIL;
- private int GetILOffsetFromFile (int methodToken, int nativeOffset)
+ private int GetILOffsetFromFile (int methodToken, uint methodIndex, int nativeOffset)
{
if (string.IsNullOrEmpty (seqPointDataPath))
return -1;
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, nativeOffset});
+ return (int) methodGetIL.Invoke (null, new object[] {seqPointDataPath, methodToken, methodIndex, nativeOffset});
+ }
+
+ static MethodInfo methodGetMethodFullName;
+ private string GetMethodFullName (MethodBase m)
+ {
+
+ if (methodGetMethodFullName == null)
+ methodGetMethodFullName = typeof (Exception).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});
+
+ return sb.ToString ();
}
}
if (!File.Exists (assemblyPath))
throw new ArgumentException ("assemblyPath does not exist: "+ assemblyPath);
- var assembly = AssemblyDefinition.ReadAssembly (assemblyPath);
+ var assembly = Assembly.LoadFrom (assemblyPath);
MonoSymbolFile symbolFile = null;
var symbolPath = assemblyPath + ".mdb";
directories.Add (Path.GetDirectoryName (assemblyPath));
- foreach (var assemblyRef in assembly.MainModule.AssemblyReferences) {
+ foreach (var assemblyRef in assembly.GetReferencedAssemblies ()) {
string refPath = null;
foreach (var dir in directories) {
refPath = Path.Combine (dir, assemblyRef.Name);
directories.Add (directory);
}
- public bool TryGetLocation (string methodName, string[] methodParams, int offset, bool isOffsetIL, out Location location)
+ public bool TryGetLocation (string method, string typeFullName, int offset, bool isOffsetIL, uint methodIndex, out Location location)
{
location = default (Location);
foreach (var assembly in assemblies.Values) {
- if (assembly.TryGetLocation (methodName, methodParams, offset, isOffsetIL, out location))
+ if (assembly.TryGetLocation (method, typeFullName, offset, isOffsetIL, methodIndex, out location))
return true;
}
LIB_PATH = $(topdir)/class/lib/$(PROFILE)
-MONO = MONO_PATH=$(LIB_PATH)$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH $(RUNTIME)
+MONO = MONO_PATH=$(LIB_PATH)$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH $(RUNTIME) -O=-inline
OUT_DIR = Test/out
TEST_CS = Test/StackTraceDumper.cs
using System;
+using System.Collections.Generic;
class StackTraceDumper {
- public static void Main () {
- // Stacktrace with no depth
+
+ public static void Main ()
+ {
+ try {
+ throw new Exception ("Stacktrace with 1 frame");
+ } catch (Exception e) {
+ Console.WriteLine (e);
+ }
+
+ try {
+ ThrowException ("Stacktrace with 2 frames");
+ } catch (Exception e) {
+ Console.WriteLine (e);
+ }
+
try {
- throw new Exception ();
+ ThrowException ("Stacktrace with 3 frames", 2);
} catch (Exception e) {
Console.WriteLine (e);
}
- // Stacktrace with depth of 1
+
+ try {
+ var message = "Stack frame with method overload using ref parameter";
+ ThrowException (ref message);
+ } catch (Exception e) {
+ Console.WriteLine (e);
+ }
+
+ try {
+ int i;
+ ThrowException ("Stack frame with method overload using out parameter", out i);
+ } catch (Exception e) {
+ Console.WriteLine (e);
+ }
+
try {
- ThrowException ();
+ ThrowExceptionGeneric<double> ("Stack frame with 1 generic parameter");
} catch (Exception e) {
Console.WriteLine (e);
}
- // Stacktrace with depth of 2
+
+ try {
+ ThrowExceptionGeneric<double,string> ("Stack frame with 2 generic parameters");
+ } catch (Exception e) {
+ Console.WriteLine (e);
+ }
+
+ try {
+ ThrowExceptionGeneric (12);
+ } catch (Exception e) {
+ Console.WriteLine (e);
+ }
+
+ try {
+ InnerClass.ThrowException ("Stack trace with inner class");
+ } catch (Exception e) {
+ Console.WriteLine (e);
+ }
+
+ try {
+ InnerGenericClass<string>.ThrowException ("Stack trace with inner generic class");
+ } catch (Exception e) {
+ Console.WriteLine (e);
+ }
+
try {
- ThrowException2 ();
+ InnerGenericClass<string>.ThrowException ("Stack trace with inner generic class and method generic parameter", "string");
} catch (Exception e) {
Console.WriteLine (e);
}
+
+ try {
+ InnerGenericClass<string>.ThrowException<string> ("Stack trace with inner generic class and generic overload", "string");
+ } catch (Exception e) {
+ Console.WriteLine (e);
+ }
+
+ try {
+ InnerGenericClass<string>.InnerInnerGenericClass<int>.ThrowException ("Stack trace with 2 inner generic class and generic overload");
+ } catch (Exception e) {
+ Console.WriteLine (e);
+ }
+
+ try {
+ InnerGenericClass<int>.InnerInnerGenericClass<string>.ThrowException ("Stack trace with 2 inner generic class and generic overload");
+ } catch (Exception e) {
+ Console.WriteLine (e);
+ }
+ }
+
+ public static void ThrowException (string message)
+ {
+ throw new Exception (message);
+ }
+
+ public static void ThrowException (ref string message)
+ {
+ throw new Exception (message);
+ }
+
+ public static void ThrowException (string message, int i)
+ {
+ if (i > 1)
+ ThrowException (message, --i);
+
+ throw new Exception (message);
+ }
+
+ public static void ThrowException (string message, out int o)
+ {
+ throw new Exception (message);
}
- public static void ThrowException () {
- Console.WriteLine ("Exception is not in the first line!");
- throw new Exception ();
+ public static void ThrowExceptionGeneric<T> (string message)
+ {
+ throw new Exception (message);
}
- public static void ThrowException2 () {
- ThrowException ();
+ public static void ThrowExceptionGeneric<T> (T a1)
+ {
+ throw new Exception ("Stack frame with generic method overload");
}
+ public static void ThrowExceptionGeneric<T> (List<string> a1)
+ {
+ throw new Exception ("Stack frame with generic method overload");
+ }
+
+ public static void ThrowExceptionGeneric<T> (List<T> a1)
+ {
+ throw new Exception ("Stack frame with generic method overload");
+ }
+
+ public static void ThrowExceptionGeneric<T1,T2> (string message)
+ {
+ throw new Exception (message);
+ }
+
+ class InnerClass {
+ public static void ThrowException (string message)
+ {
+ throw new Exception (message);
+ }
+ }
+
+ class InnerGenericClass<T> {
+ public static void ThrowException (string message)
+ {
+ throw new Exception (message);
+ }
+
+ public static void ThrowException (string message, T arg)
+ {
+ Console.WriteLine ("Generic to string:" + arg.ToString());
+ throw new Exception (message);
+ }
+
+ public static void ThrowException<T1> (string message, T1 arg)
+ {
+ throw new Exception (message);
+ }
+
+ public class InnerInnerGenericClass<T2> {
+ public static void ThrowException (T message)
+ {
+ throw new Exception (message as string);
+ }
+
+ public static void ThrowException (T2 message)
+ {
+ throw new Exception (message as string);
+ }
+ }
+ }
}
\ No newline at end of file
-System.Exception: Exception of type 'System.Exception' was thrown.
- at StackTraceDumper.Main () in StackTraceDumper.cs:7
-Exception is not in the first line!
-System.Exception: Exception of type 'System.Exception' was thrown.
- at StackTraceDumper.ThrowException () in StackTraceDumper.cs:27
- at StackTraceDumper.Main () in StackTraceDumper.cs:13
-Exception is not in the first line!
-System.Exception: Exception of type 'System.Exception' was thrown.
- at StackTraceDumper.ThrowException () in StackTraceDumper.cs:27
- at StackTraceDumper.ThrowException2 () in StackTraceDumper.cs:31
- at StackTraceDumper.Main () in StackTraceDumper.cs:19
+System.Exception: Stacktrace with 1 frame
+ at StackTraceDumper.Main () in StackTraceDumper.cs:9
+System.Exception: Stacktrace with 2 frames
+ at StackTraceDumper.ThrowException (System.String message) in StackTraceDumper.cs:97
+ at StackTraceDumper.Main () in StackTraceDumper.cs:15
+System.Exception: Stacktrace with 3 frames
+ at StackTraceDumper.ThrowException (System.String message, Int32 i) in StackTraceDumper.cs:110
+ at StackTraceDumper.ThrowException (System.String message, Int32 i) in StackTraceDumper.cs:108
+ at StackTraceDumper.Main () in StackTraceDumper.cs:21
+System.Exception: Stack frame with method overload using ref parameter
+ at StackTraceDumper.ThrowException (System.String& message) in StackTraceDumper.cs:102
+ at StackTraceDumper.Main () in StackTraceDumper.cs:28
+System.Exception: Stack frame with method overload using out parameter
+ at StackTraceDumper.ThrowException (System.String message, System.Int32& o) in StackTraceDumper.cs:115
+ at StackTraceDumper.Main () in StackTraceDumper.cs:35
+System.Exception: Stack frame with 1 generic parameter
+ at StackTraceDumper.ThrowExceptionGeneric[T] (System.String message) in StackTraceDumper.cs:120
+ at StackTraceDumper.Main () in StackTraceDumper.cs:41
+System.Exception: Stack frame with 2 generic parameters
+ at StackTraceDumper.ThrowExceptionGeneric[T1,T2] (System.String message) in StackTraceDumper.cs:140
+ at StackTraceDumper.Main () in StackTraceDumper.cs:47
+System.Exception: Stack frame with generic method overload
+ at StackTraceDumper.ThrowExceptionGeneric[T] (T a1) in StackTraceDumper.cs:125
+ at StackTraceDumper.Main () in StackTraceDumper.cs:53
+System.Exception: Stack trace with inner class
+ at StackTraceDumper+InnerClass.ThrowException (System.String message) in StackTraceDumper.cs:146
+ at StackTraceDumper.Main () in StackTraceDumper.cs:59
+System.Exception: Stack trace with inner generic class
+ at StackTraceDumper+InnerGenericClass`1[T].ThrowException (System.String message) in StackTraceDumper.cs:153
+ at StackTraceDumper.Main () in StackTraceDumper.cs:65
+Generic to string:string
+System.Exception: Stack trace with inner generic class and method generic parameter
+ at StackTraceDumper+InnerGenericClass`1[T].ThrowException (System.String message, T arg) in StackTraceDumper.cs:159
+ at StackTraceDumper.Main () in StackTraceDumper.cs:71
+System.Exception: Stack trace with inner generic class and generic overload
+ at StackTraceDumper+InnerGenericClass`1[T].ThrowException[T1] (System.String message, T1 arg) in StackTraceDumper.cs:164
+ at StackTraceDumper.Main () in StackTraceDumper.cs:77
+System.Exception: Stack trace with 2 inner generic class and generic overload
+ at StackTraceDumper+InnerGenericClass`1+InnerInnerGenericClass`1[T,T2].ThrowException (T message) in StackTraceDumper.cs:170
+ at StackTraceDumper.Main () in StackTraceDumper.cs:83
+System.Exception: Stack trace with 2 inner generic class and generic overload
+ at StackTraceDumper+InnerGenericClass`1+InnerInnerGenericClass`1[T,T2].ThrowException (T2 message) in StackTraceDumper.cs:175
+ at StackTraceDumper.Main () in StackTraceDumper.cs:89
{
public class Program
{
- static Regex regex = new Regex (@"\w*at (?<MethodName>.+) \((?<MethodParams>.*)\) *(\[0x(?<IL>.+)\]|<0x.* \+ 0x(?<NativeOffset>.+)>) in <filename unknown>:0");
+ static Regex regex = new Regex (@"\w*at (?<Method>.+) *(\[0x(?<IL>.+)\]|<0x.+ \+ 0x(?<NativeOffset>.+)>( (?<MethodIndex>\d+)|)) in <filename unknown>:0");
public static int Main (String[] args)
{
if (!match.Success)
return line;
- var methodName = match.Groups ["MethodName"].Value;
- var methodParams = ParseParametersTypes (match.Groups ["MethodParams"].Value);
+ string typeFullName;
+ var methodStr = match.Groups ["Method"].Value.Trim ();
+ if (!TryParseMethodType (methodStr, out typeFullName))
+ return line;
var isOffsetIL = !string.IsNullOrEmpty (match.Groups ["IL"].Value);
var offsetVarName = (isOffsetIL)? "IL" : "NativeOffset";
var offset = int.Parse (match.Groups [offsetVarName].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
+ uint methodIndex = 0xffffff;
+ if (!string.IsNullOrEmpty (match.Groups ["MethodIndex"].Value))
+ methodIndex = uint.Parse (match.Groups ["MethodIndex"].Value, CultureInfo.InvariantCulture);
+
Location location;
- if (!locProvider.TryGetLocation (methodName, methodParams, offset, isOffsetIL, out location))
+ if (!locProvider.TryGetLocation (methodStr, typeFullName, offset, isOffsetIL, methodIndex, out location))
return line;
return line.Replace ("<filename unknown>:0", string.Format ("{0}:{1}", location.FileName, location.Line));
}
- static string[] ParseParametersTypes (string parameters)
+ static bool TryParseMethodType (string str, out string typeFullName)
{
- if (string.IsNullOrEmpty (parameters))
- return new string [0];
+ typeFullName = null;
+
+ var methodNameEnd = str.IndexOf ("(");
+ if (methodNameEnd == -1)
+ return false;
+
+ // Remove parameters
+ str = str.Substring (0, methodNameEnd);
+
+ // Remove generic parameters
+ str = Regex.Replace (str, @"\[[^\[\]]*\]", "");
+
+ var typeNameEnd = str.LastIndexOf (".");
+ if (methodNameEnd == -1 || typeNameEnd == -1)
+ return false;
- var paramsArray = parameters.Split (',');
- var paramsTypes = new string [paramsArray.Length];
- for (var i = 0; i < paramsArray.Length; i++)
- paramsTypes [i] = paramsArray [i].Trim ().Split (new char[]{' '}, 2)[0];
+ // Remove method name
+ typeFullName = str.Substring (0, typeNameEnd);
- return paramsTypes;
+ return true;
}
}
}
\ No newline at end of file
* Changes which are already detected at runtime, like the addition
* of icalls, do not require an increment.
*/
-#define MONO_CORLIB_VERSION 123
+#define MONO_CORLIB_VERSION 124
typedef struct
{
}
ICALL_EXPORT int
-ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, int methodToken, int nativeOffset)
+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 (!seq_point_data_get_il_offset (path_str, methodToken, nativeOffset, &il_offset))
+ if (!seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
il_offset = -1;
g_free (path_str);
gint32 il_offset;
gint32 native_offset;
gint64 method_address;
+ gint32 method_index;
MonoReflectionMethod *method;
MonoString *filename;
gint32 line;
data->entry_count = entry_count;
for (i=0; i<entry_count; i++) {
- data->entries [i].token = decode_var_int (buffer, &buffer);
+ data->entries [i].method_token = decode_var_int (buffer, &buffer);
+ data->entries [i].method_index = decode_var_int (buffer, &buffer);
buffer += seq_point_info_read (&data->entries [i].seq_points, buffer, TRUE);
data->entries [i].free_seq_points = TRUE;
}
encode_var_int (buffer, &buffer, data->entry_count);
for (i=0; i<data->entry_count; i++) {
- encode_var_int (buffer, &buffer, data->entries [i].token);
+ encode_var_int (buffer, &buffer, data->entries [i].method_token);
+ encode_var_int (buffer, &buffer, data->entries [i].method_index);
buffer += seq_point_info_write (data->entries [i].seq_points, buffer);
}
}
void
-seq_point_data_add (SeqPointData *data, guint32 token, MonoSeqPointInfo* info)
+seq_point_data_add (SeqPointData *data, guint32 method_token, guint32 method_index, MonoSeqPointInfo* info)
{
int i;
g_assert (data->entry_count < data->entry_capacity);
i = data->entry_count++;
data->entries [i].seq_points = info;
- data->entries [i].token = token;
+ data->entries [i].method_token = method_token;
+ data->entries [i].method_index = method_index;
data->entries [i].free_seq_points = FALSE;
}
gboolean
-seq_point_data_get (SeqPointData *data, guint32 token, MonoSeqPointInfo** info)
+seq_point_data_get (SeqPointData *data, guint32 method_token, guint32 method_index, MonoSeqPointInfo** info)
{
int i;
for (i=0; i<data->entry_count; i++) {
- if (data->entries [i].token == token) {
+ if (data->entries [i].method_token == method_token && (method_index == 0xffffff || data->entries [i].method_index == method_index)) {
(*info) = data->entries [i].seq_points;
return TRUE;
}
}
gboolean
-seq_point_data_get_il_offset (char *path, guint32 token, guint32 native_offset, guint32 *il_offset)
+seq_point_data_get_il_offset (char *path, guint32 method_token, guint32 method_index, guint32 native_offset, guint32 *il_offset)
{
SeqPointData sp_data;
MonoSeqPointInfo *seq_points;
if (!seq_point_data_read (&sp_data, path))
return FALSE;
- if (!seq_point_data_get (&sp_data, token, &seq_points))
+ if (!seq_point_data_get (&sp_data, method_token, method_index, &seq_points))
return FALSE;
if (!seq_point_find_prev_by_native_offset (seq_points, native_offset, &sp))
*/
typedef struct {
- guint32 token;
+ guint32 method_token;
+ guint32 method_index;
MonoSeqPointInfo* seq_points;
gboolean free_seq_points;
} SeqPointDataEntry;
seq_point_data_write (SeqPointData *data, char *path);
void
-seq_point_data_add (SeqPointData *data, guint32 token, MonoSeqPointInfo* info);
+seq_point_data_add (SeqPointData *data, guint32 methodToken, guint32 methodIndex, MonoSeqPointInfo* info);
gboolean
-seq_point_data_get (SeqPointData *data, guint32 token, MonoSeqPointInfo** info);
+seq_point_data_get (SeqPointData *data, guint32 methodToken, guint32 methodIndex, MonoSeqPointInfo** info);
gboolean
-seq_point_data_get_il_offset (char *path, guint32 token, guint32 native_offset, guint32 *il_offset);
+seq_point_data_get_il_offset (char *path, guint32 methodToken, guint32 methodIndex, guint32 native_offset, guint32 *il_offset);
#endif /* __MONO_SEQ_POINTS_DATA_H__ */
\ No newline at end of file
seq_point_data_init (&sp_data, acfg->nmethods);
seq_points_to_file = TRUE;
}
- seq_point_data_add (&sp_data, cfg->method->token, cfg->seq_point_info);
+ seq_point_data_add (&sp_data, cfg->method->token, cfg->method_index, cfg->seq_point_info);
}
} else {
offsets [i] = 0;
return index;
}
+guint32
+mono_aot_find_method_index (MonoMethod *method)
+{
+ MonoAotModule *out_amodule;
+ return find_aot_method (method, &out_amodule);
+}
+
/*
* mono_aot_get_method:
*
}
else
MONO_OBJECT_SETREF (sf, method, mono_method_get_object (domain, method, NULL));
+
+ sf->method_index = ji->from_aot ? mono_aot_find_method_index (method) : 0xffffff;
sf->method_address = (gsize) ji->code_start;
sf->native_offset = (char *)ip - (char *)ji->code_start;
void mono_aot_handle_pagefault (void *ptr);
void mono_aot_register_jit_icall (const char *name, gpointer addr);
void* mono_aot_readonly_field_override (MonoClassField *field);
+guint32 mono_aot_find_method_index (MonoMethod *method);
/* This is an exported function */
MONO_API void mono_aot_register_globals (gpointer *globals);