@@ -147,6 +147,14 @@ mono_arch_exceptions_init (void)
147
147
// NOT_IMPLEMENTED;
148
148
}
149
149
150
+ /*
151
+ * mono_arch_unwind_frame:
152
+ *
153
+ * This function is used to gather information from @ctx, and store it in @frame_info.
154
+ * It unwinds one stack frame, and stores the resulting context into @new_ctx. @lmf
155
+ * is modified if needed.
156
+ * Returns TRUE on success, FALSE otherwise.
157
+ */
150
158
gboolean
151
159
mono_arch_unwind_frame (MonoJitTlsData * jit_tls , MonoJitInfo * ji ,
152
160
MonoContext * ctx , MonoContext * new_ctx , MonoLMF * * lmf ,
@@ -160,7 +168,7 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, MonoJitInfo *ji,
160
168
* new_ctx = * ctx ;
161
169
162
170
if (ji != NULL ) {
163
- NOT_IMPLEMENTED ;
171
+ // all GREG + Callee saved FREG
164
172
host_mgreg_t regs [MONO_MAX_IREGS + 12 + 1 ];
165
173
guint8 * cfa ;
166
174
guint32 unwind_info_len ;
@@ -182,10 +190,9 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, MonoJitInfo *ji,
182
190
for (int i = 0 ; i < 10 ; i ++ )
183
191
(regs + MONO_MAX_IREGS ) [i ] = * ((host_mgreg_t * )& new_ctx -> fregs [RISCV_F18 + i ]);
184
192
185
- gboolean success = mono_unwind_frame (unwind_info , unwind_info_len , (guint8 * )ji -> code_start ,
186
- (guint8 * )ji -> code_start + ji -> code_size ,
187
- (guint8 * )ip , NULL , regs , MONO_MAX_IREGS + 8 ,
188
- save_locations , MONO_MAX_IREGS , (guint8 * * )& cfa );
193
+ gboolean success = mono_unwind_frame (unwind_info , unwind_info_len , (guint8 * )ji -> code_start ,
194
+ (guint8 * )ji -> code_start + ji -> code_size , (guint8 * )ip , NULL , regs ,
195
+ MONO_MAX_IREGS + 12 + 1 , save_locations , MONO_MAX_IREGS , (guint8 * * )& cfa );
189
196
190
197
if (!success )
191
198
return FALSE;
@@ -198,15 +205,33 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, MonoJitInfo *ji,
198
205
199
206
new_ctx -> gregs [RISCV_SP ] = (host_mgreg_t )(gsize )cfa ;
200
207
201
- if (* lmf )
202
- NOT_IMPLEMENTED ;
208
+ if (* lmf && (* lmf )-> gregs [RISCV_FP ] && (MONO_CONTEXT_GET_SP (ctx ) >= (gpointer )(* lmf )-> gregs [RISCV_SP ])) {
209
+ /* remove any unused lmf */
210
+ * lmf = (MonoLMF * )(((gsize )(* lmf )-> previous_lmf ) & ~(TARGET_SIZEOF_VOID_P - 1 ));
211
+ }
203
212
204
- /* we subtract 1, so that the IP points into the call instruction */
213
+ /* we substract 1, so that the pc points into the call instruction */
205
214
new_ctx -> gregs [RISCV_ZERO ]-- ;
206
215
207
216
return TRUE;
208
217
} else if (* lmf ) {
209
- NOT_IMPLEMENTED ;
218
+ g_assert ((((guint64 )(* lmf )-> previous_lmf ) & 2 ) == 0 );
219
+
220
+ frame -> type = FRAME_TYPE_MANAGED_TO_NATIVE ;
221
+
222
+ ji = mini_jit_info_table_find ((gpointer )(* lmf )-> pc );
223
+ if (!ji )
224
+ return FALSE;
225
+
226
+ memcpy (& new_ctx -> gregs , (* lmf )-> gregs , sizeof (host_mgreg_t ) * RISCV_N_GREGS );
227
+ new_ctx -> gregs [0 ] = (* lmf )-> pc ; // use [0] as pc reg since x0 is hard-wired zero
228
+
229
+ /* we substract 1, so that the IP points into the call instruction */
230
+ new_ctx -> gregs [0 ]-- ;
231
+
232
+ * lmf = (MonoLMF * )(((gsize )(* lmf )-> previous_lmf ) & ~(TARGET_SIZEOF_VOID_P - 1 ));
233
+
234
+ return TRUE;
210
235
}
211
236
212
237
return FALSE;
0 commit comments