1
1
using System ;
2
2
using System . Diagnostics ;
3
3
using System . Diagnostics . CodeAnalysis ;
4
+ using System . Globalization ;
4
5
using System . Reflection ;
6
+ using System . Text ;
5
7
6
8
using StackTraceElement = Java . Lang . StackTraceElement ;
7
9
@@ -37,6 +39,81 @@ public static JavaProxyThrowable Create (Exception innerException)
37
39
return proxy ;
38
40
}
39
41
42
+ ( int lineNumber , string ? methodName , string ? className ) GetFrameInfo ( StackFrame ? managedFrame , MethodBase ? managedMethod )
43
+ {
44
+ string ? methodName = null ;
45
+ string ? className = null ;
46
+
47
+ if ( managedFrame == null ) {
48
+ if ( managedMethod != null ) {
49
+ methodName = managedMethod . Name ;
50
+ className = managedMethod . DeclaringType ? . FullName ;
51
+ }
52
+
53
+ return ( - 1 , methodName , className ) ;
54
+ }
55
+
56
+ int lineNumber = - 1 ;
57
+ lineNumber = managedFrame . GetFileLineNumber ( ) ;
58
+ if ( lineNumber == 0 ) {
59
+ // -2 means it's a native frame
60
+ lineNumber = managedFrame . HasNativeImage ( ) ? - 2 : - 1 ;
61
+ }
62
+
63
+ if ( managedMethod != null ) {
64
+ // If we have no line number information and if it's a managed frame, add the
65
+ // IL offset.
66
+ if ( lineNumber == - 1 && managedFrame . HasILOffset ( ) ) {
67
+ methodName = $ "{ managedMethod . Name } + 0x{ managedFrame . HasILOffset : x} ";
68
+ } else {
69
+ methodName = managedMethod . Name ;
70
+ }
71
+
72
+ return ( lineNumber , methodName , managedMethod . DeclaringType ? . FullName ) ;
73
+ }
74
+
75
+ string frameString = managedFrame . ToString ( ) ;
76
+ var sb = new StringBuilder ( ) ;
77
+
78
+ // We take the part of the returned string that stretches from the beginning to the first space character
79
+ // and treat it as the method name.
80
+ // https://github.com/dotnet/runtime/blob/18c3ad05c3fc127c3b7f37c49bc350bf7f8264a0/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/DeveloperExperience/DeveloperExperience.cs#L15-L55
81
+ int pos = frameString . IndexOf ( ' ' ) ;
82
+ string ? fullName = null ;
83
+ if ( pos > 1 ) {
84
+ fullName = frameString . Substring ( 0 , pos ) ;
85
+ }
86
+
87
+ if ( ! String . IsNullOrEmpty ( fullName ) && ( pos = fullName . LastIndexOf ( '.' ) ) >= 1 ) {
88
+ className = pos + 1 < fullName . Length ? fullName . Substring ( pos + 1 ) : null ;
89
+ fullName = fullName . Substring ( 0 , pos ) ;
90
+ }
91
+
92
+ if ( ! String . IsNullOrEmpty ( fullName ) ) {
93
+ sb . Append ( fullName ) ;
94
+ } else if ( managedFrame . HasNativeImage ( ) ) {
95
+ // We have no name, so we'll put the native IP
96
+ nint nativeIP = managedFrame . GetNativeIP ( ) ;
97
+ sb . Append ( CultureInfo . InvariantCulture , $ "Native 0x{ nativeIP : x} ") ;
98
+ }
99
+
100
+ if ( sb . Length > 0 ) {
101
+ // We will also append information native offset information, if available and only if we
102
+ // have recorded any previous information, since the offset without context is useless.
103
+ int nativeOffset = managedFrame . GetNativeOffset ( ) ;
104
+ if ( nativeOffset != StackFrame . OFFSET_UNKNOWN ) {
105
+ sb . Append ( " + " ) ;
106
+ sb . Append ( CultureInfo . InvariantCulture , $ "0x{ nativeOffset : x} ") ;
107
+ }
108
+ }
109
+
110
+ if ( sb . Length > 0 ) {
111
+ methodName = sb . ToString ( ) ;
112
+ }
113
+
114
+ return ( lineNumber , methodName , className ) ;
115
+ }
116
+
40
117
void TranslateStackTrace ( )
41
118
{
42
119
// FIXME: https://github.com/xamarin/xamarin-android/issues/8724
@@ -61,7 +138,6 @@ void TranslateStackTrace ()
61
138
// ..but ignore
62
139
}
63
140
64
-
65
141
StackFrame [ ] frames = trace . GetFrames ( ) ;
66
142
int nElements = frames . Length + ( javaTrace ? . Length ?? 0 ) ;
67
143
StackTraceElement [ ] elements = new StackTraceElement [ nElements ] ;
@@ -72,20 +148,10 @@ void TranslateStackTrace ()
72
148
MethodBase ? managedMethod = StackFrameGetMethod ( managedFrame ) ;
73
149
74
150
// https://developer.android.com/reference/java/lang/StackTraceElement?hl=en#StackTraceElement(java.lang.String,%20java.lang.String,%20java.lang.String,%20int)
75
- int lineNumber ;
76
- if ( managedFrame != null ) {
77
- lineNumber = managedFrame . GetFileLineNumber ( ) ;
78
- if ( lineNumber == 0 ) {
79
- // -2 means it's a native frame
80
- lineNumber = managedFrame . HasNativeImage ( ) ? - 2 : - 1 ;
81
- }
82
- } else {
83
- lineNumber = - 1 ;
84
- }
85
-
151
+ ( int lineNumber , string ? methodName , string ? declaringClass ) = GetFrameInfo ( managedFrame , managedMethod ) ;
86
152
var throwableFrame = new StackTraceElement (
87
- declaringClass : managedMethod ? . DeclaringType ? . FullName ?? Unknown ,
88
- methodName : managedMethod ? . Name ?? Unknown ,
153
+ declaringClass : declaringClass ?? Unknown ,
154
+ methodName : methodName ?? Unknown ,
89
155
fileName : managedFrame ? . GetFileName ( ) ,
90
156
lineNumber : lineNumber
91
157
) ;
0 commit comments