Skip to content

Commit 0c513c6

Browse files
committed
Attempt to capture stack trace on GPF
1 parent 968d2fc commit 0c513c6

File tree

6 files changed

+123
-21
lines changed

6 files changed

+123
-21
lines changed

bitwise.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ DWORD __declspec(dllexport) __stdcall Bitwise_And (vm_state *vm, DWORD arg_count
66
DWORD isnull;
77
DWORD a1, a2;
88
value v;
9+
last_vm = vm;
10+
911
a1=ot_get_ulongarg(vm, &isnull);
1012
if (isnull) a1=0;
1113
a2=ot_get_ulongarg(vm, &isnull);
@@ -21,6 +23,8 @@ DWORD __declspec(dllexport) __stdcall Bitwise_Or (vm_state *vm, DWORD arg_count)
2123
DWORD isnull;
2224
DWORD a1, a2;
2325
value v;
26+
last_vm = vm;
27+
2428
a1=ot_get_ulongarg(vm, &isnull);
2529
if (isnull) a1=0;
2630
a2=ot_get_ulongarg(vm, &isnull);
@@ -36,6 +40,8 @@ DWORD __declspec(dllexport) __stdcall Bitwise_Xor (vm_state *vm, DWORD arg_count
3640
DWORD isnull;
3741
DWORD a1, a2;
3842
value v;
43+
last_vm = vm;
44+
3945
a1=ot_get_ulongarg(vm, &isnull);
4046
if (isnull) a1=0;
4147
a2=ot_get_ulongarg(vm, &isnull);
@@ -51,6 +57,8 @@ DWORD __declspec(dllexport) __stdcall Bitwise_Not (vm_state *vm, DWORD arg_count
5157
DWORD isnull;
5258
DWORD a1;
5359
value v;
60+
last_vm = vm;
61+
5462
a1=ot_get_ulongarg(vm, &isnull);
5563
if (isnull) a1=0;
5664
v.value=~a1;
@@ -64,6 +72,8 @@ DWORD __declspec(dllexport) __stdcall Bitwise_Shift_Left (vm_state *vm, DWORD ar
6472
DWORD isnull;
6573
DWORD a1, a2;
6674
value v;
75+
last_vm = vm;
76+
6777
a1=ot_get_ulongarg(vm, &isnull);
6878
if (isnull) a1=0;
6979
a2=ot_get_ulongarg(vm, &isnull);
@@ -79,6 +89,8 @@ DWORD __declspec(dllexport) __stdcall Bitwise_Shift_Right (vm_state *vm, DWORD a
7989
DWORD isnull;
8090
DWORD a1, a2;
8191
value v;
92+
last_vm = vm;
93+
8294
a1=ot_get_ulongarg(vm, &isnull);
8395
if (isnull) a1=0;
8496
a2=ot_get_ulongarg(vm, &isnull);
@@ -93,6 +105,8 @@ DWORD __declspec(dllexport) __stdcall Bitwise_Shift_Right (vm_state *vm, DWORD a
93105
DWORD __declspec(dllexport) __stdcall Address (vm_state *vm, DWORD arg_count){
94106
value v;
95107

108+
last_vm = vm;
109+
96110
value *v_value = ot_get_next_evaled_arg_no_convert(vm);
97111
if (v_value->flags&IS_NULL){
98112
v.value=0;

blob_funcs.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ DWORD __declspec(dllexport) __stdcall Blob_Extract (vm_state *vm, DWORD arg_coun
144144
value ret, *val, *v_pos;
145145
blob *source;
146146

147+
last_vm = vm;
148+
147149
lv_val = ot_get_next_lvalue_arg(vm,&isnull);
148150
val = get_lvalue(vm, lv_val);
149151

@@ -168,6 +170,8 @@ DWORD __declspec(dllexport) __stdcall Get_Byte_Array (vm_state *vm, DWORD arg_co
168170
blob *source;
169171
value ret;
170172

173+
last_vm = vm;
174+
171175
source=(blob *)ot_get_valptr_arg(vm, &isnull);
172176
len=source->len;
173177
if (arg_count>=2){
@@ -307,6 +311,8 @@ DWORD __declspec(dllexport) __stdcall Blob_Import (vm_state *vm, DWORD arg_count
307311
lvalue_ref *lv_pos;
308312
value *v_pos;
309313

314+
last_vm = vm;
315+
310316
value *v_value = ot_get_next_evaled_arg_no_convert(vm);
311317

312318
lvalue_ref *lv_data = ot_get_next_lvalue_arg(vm,&isnull);
@@ -337,6 +343,8 @@ DWORD __declspec(dllexport) __stdcall Blob_Mid (vm_state *vm, DWORD arg_count){
337343
blob *source, *dest;
338344
value v;
339345

346+
last_vm = vm;
347+
340348
source = (blob *)ot_get_valptr_arg(vm, &isnull);
341349
if (isnull || source==NULL || source->len==0){
342350
len =0;
@@ -374,6 +382,8 @@ DWORD __declspec(dllexport) __stdcall Blob_Alloc (vm_state *vm, DWORD arg_count)
374382
int zero_memory=FALSE;
375383
value v;
376384

385+
last_vm = vm;
386+
377387
new_size=ot_get_ulongarg(vm, &isnull);
378388
if (isnull) new_size=0;
379389

dllmain.cpp

+31-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "pbvm.h"
22

3+
vm_state *last_vm = NULL;
34

45
value * get_lvalue(vm_state *vm, lvalue_ref *value_ref){
56
lvalue *v=value_ref->ptr;
@@ -88,6 +89,8 @@ DWORD __declspec(dllexport) __stdcall Split (vm_state *vm, DWORD arg_count){
8889
lvalue_ref *lv_values;
8990
value ret;
9091

92+
last_vm = vm;
93+
9194
source = (wchar_t *)ot_get_valptr_arg(vm, &source_null);
9295
delim = (wchar_t *)ot_get_valptr_arg(vm, &delim_null);
9396

@@ -151,6 +154,8 @@ DWORD __declspec(dllexport) __stdcall Token2 (vm_state *vm, DWORD arg_count){
151154
lvalue_ref *lv_source, *lv_token;
152155
value ret, *v_source;
153156

157+
last_vm = vm;
158+
154159
ret.value=TRUE;
155160
ret.type=7;
156161
ret.flags=0x0500;
@@ -212,6 +217,8 @@ DWORD __declspec(dllexport) __stdcall Token (vm_state *vm, DWORD arg_count){
212217
lvalue_ref *lv_pos, *lv_token;
213218
value ret, *v_pos;
214219

220+
last_vm = vm;
221+
215222
ret.value=TRUE;
216223
ret.type=7;
217224
ret.flags=0x0500;
@@ -279,6 +286,8 @@ DWORD __declspec(dllexport) __stdcall Next_Tag (vm_state *vm, DWORD arg_count){
279286
lvalue_ref *lv_pos, *lv_tag;
280287
value ret, *v_pos;
281288

289+
last_vm = vm;
290+
282291
ret.value=TRUE;
283292
ret.type=7;
284293
ret.flags=0x0500;
@@ -391,6 +400,8 @@ DWORD __declspec(dllexport) __stdcall Sort (vm_state *vm, DWORD arg_count){
391400
value *v_array1, *v_array2;
392401
pb_array *array1, *array2;
393402

403+
last_vm = vm;
404+
394405
ret.type=1;
395406
ret.flags=0x500;
396407
ret.value=1;
@@ -476,6 +487,8 @@ DWORD __declspec(dllexport) __stdcall Sort (vm_state *vm, DWORD arg_count){
476487

477488
DWORD __declspec(dllexport) __stdcall Index (vm_state *vm, DWORD arg_count){
478489
value ret;
490+
last_vm = vm;
491+
479492
value *v_find = ot_get_next_evaled_arg_no_convert(vm);
480493
value *v_array = ot_get_next_evaled_arg_no_convert(vm);
481494

@@ -578,6 +591,8 @@ DWORD __declspec(dllexport) __stdcall Fast_Pos (vm_state *vm, DWORD arg_count){
578591
wchar_t *source, *find;
579592
value v;
580593

594+
last_vm = vm;
595+
581596
source = (wchar_t *)ot_get_valptr_arg(vm, &source_null);
582597
find = (wchar_t *)ot_get_valptr_arg(vm, &find_null);
583598

@@ -607,6 +622,8 @@ DWORD __declspec(dllexport) __stdcall Last_Pos (vm_state *vm, DWORD arg_count){
607622
wchar_t *source, *find;
608623
value v;
609624

625+
last_vm = vm;
626+
610627
source = (wchar_t *)ot_get_valptr_arg(vm, &source_null);
611628
find = (wchar_t *)ot_get_valptr_arg(vm, &find_null);
612629

@@ -662,13 +679,15 @@ DWORD __declspec(dllexport) __stdcall Last_Pos (vm_state *vm, DWORD arg_count){
662679
return 1;
663680
}
664681

665-
// string Replace_All (readonly string source, readonly string find, readonly string replace)
682+
// string Replace_All (readonly string source, readonly string find, readonly string replace [, boolean case_sensitive])
666683
DWORD __declspec(dllexport) __stdcall Replace_All (vm_state *vm, DWORD arg_count){
667684
DWORD source_null, find_null, replace_null, ignored;
668685
wchar_t *source, *find, *replace;
669686
DWORD insensitive=FALSE;
670687
value v;
671688

689+
last_vm = vm;
690+
672691
source = (wchar_t *)ot_get_valptr_arg(vm, &source_null);
673692
find = (wchar_t *)ot_get_valptr_arg(vm, &find_null);
674693
replace = (wchar_t *)ot_get_valptr_arg(vm, &replace_null);
@@ -776,6 +795,8 @@ DWORD __declspec(dllexport) __stdcall Append (vm_state *vm, DWORD arg_count){
776795
DWORD isnull;
777796
value v;
778797

798+
last_vm = vm;
799+
779800
v.value=TRUE;
780801
v.type=7;
781802
v.flags=0x0500;
@@ -877,6 +898,8 @@ DWORD __declspec(dllexport) __stdcall Value_Info (vm_state *vm, DWORD arg_count)
877898
value v;
878899
wchar_t info[256];
879900

901+
last_vm = vm;
902+
880903
value *v_value = ot_get_next_evaled_arg_no_convert(vm);
881904

882905
DWORD len=0;
@@ -910,15 +933,20 @@ BOOL APIENTRY DllMain( HMODULE hModule,
910933
DWORD ul_reason_for_call,
911934
LPVOID lpReserved
912935
)
913-
{/*
936+
{
914937
switch (ul_reason_for_call)
915938
{
916939
case DLL_PROCESS_ATTACH:
940+
Install_Crash_Hook();
941+
break;
917942
case DLL_THREAD_ATTACH:
943+
break;
918944
case DLL_THREAD_DETACH:
945+
break;
919946
case DLL_PROCESS_DETACH:
947+
Uninstall_Crash_Hook();
920948
break;
921-
}*/
949+
}
922950
return TRUE;
923951
}
924952

orca.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ DWORD __declspec(dllexport) __stdcall Orca_Init (vm_state *vm, DWORD arg_count){
109109
orca_state *state;
110110
pb_class *obj;
111111

112+
last_vm = vm;
113+
112114
ot_get_curr_obinst_expr(vm, &obj, &isvalid);
113115
ob_get_field(vm, obj, 1, &field);
114116
if (field.value){

pbvm.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,8 @@ int __stdcall rtRoutineExec(vm_state *, int, pb_class *, int, int, value*, int,
179179

180180

181181
value * get_lvalue(vm_state *vm, lvalue_ref *value_ref);
182-
void Throw_Exception(vm_state *vm, wchar_t *text, ...);
182+
void Throw_Exception(vm_state *vm, wchar_t *text, ...);
183+
void Install_Crash_Hook();
184+
void Uninstall_Crash_Hook();
185+
186+
extern vm_state *last_vm;

stack_trace.cpp

+61-17
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,53 @@
11
#include "pbvm.h"
22

3+
34
// set of temporary values for building the stack string array.
5+
// note that stack_info->caller_line_no is the line number we are going to return to
6+
47
typedef struct{
58
vm_state *vm;
69
pb_array *values;
710
int index;
811
wchar_t *group_name;
912
wchar_t *class_name;
1013
wchar_t *routine_name;
14+
wchar_t *trace;
1115
}callback_state;
1216

17+
void set_string(vm_state *vm, wchar_t *source, value *val){
18+
int len=wcslen(source);
19+
wchar_t *dest = (wchar_t *)pbstg_alc(vm, (len+1)*2, GET_HEAP(vm));
20+
wcscpy(dest, source);
21+
22+
if (!(val->flags&IS_NULL))
23+
ot_free_val_ptr(vm, val);
24+
25+
val->value=(DWORD)dest;
26+
val->flags=0x0d00;
27+
val->type=pbvalue_string;
28+
}
29+
1330
void stack_build_string(callback_state *state, short line_no){
1431
wchar_t temp[256];
15-
value *v=ot_array_index(state->vm, state->values, state->index -1);
16-
if (!(v->flags&IS_NULL))
17-
ot_free_val_ptr(state->vm, v);
18-
19-
wnsprintf(temp, 256, L"%s.%s.%s Line: %d",state->group_name, state->class_name, state->routine_name, line_no);
20-
21-
int len=wcslen(temp);
22-
wchar_t *dest = (wchar_t *)pbstg_alc(state->vm, (len+1)*2, GET_HEAP(state->vm));
23-
wcscpy(dest,temp);
24-
v->value=(DWORD)dest;
32+
if (state->index==0 || state->group_name==NULL)
33+
return;
2534

26-
v->flags=0x0d00;
27-
v->type=pbvalue_string;
35+
wnsprintf(temp, 256, L"%s.%s.%s Line: %d",state->group_name, state->class_name, state->routine_name, line_no);
36+
if (state->values != NULL){
37+
value *val=ot_array_index(state->vm, state->values, state->index -1);
38+
set_string(state->vm, temp, val);
39+
}
40+
if (state->trace!=NULL)
41+
lstrcatW(state->trace, temp);
2842
}
2943

3044
bool __stdcall callback(stack_info *info, void * arg_value){
3145
callback_state *state=(callback_state *)arg_value;
3246

33-
if (state->index>0){
34-
stack_build_string(state, info->caller_line_no);
35-
}
47+
stack_build_string(state, info->caller_line_no);
3648
state->index++;
3749

38-
// note these are pointers to const memory addresses
50+
// note these are pointers to const memory addresses
3951
state->group_name= ob_get_group_name(state->vm, info->group_id);
4052
state->class_name = ob_class_name_not_indirect(state->vm, MAKELONG(info->group_id, info->class_id));
4153

@@ -47,24 +59,56 @@ bool __stdcall callback(stack_info *info, void * arg_value){
4759
}
4860

4961
DWORD __declspec(dllexport) __stdcall Stack_Trace (vm_state *vm, DWORD arg_count){
62+
5063
value ret;
5164
lvalue_ref *lv_values;
5265
callback_state state;
5366
DWORD isnull;
5467

68+
last_vm = vm;
69+
5570
lv_values=ot_get_next_lvalue_arg(vm, &isnull);
5671
state.values = ot_array_create_unbounded(vm, MAKELONG(-1,pbvalue_string), 0);
5772

5873
state.vm=vm;
5974
state.index=0;
75+
state.trace=NULL;
76+
state.group_name=NULL;
6077

6178
ret.value=shlist_traversal(GET_STACKLIST(vm), &state, callback);
6279
ret.type=7;
6380
ret.flags=0x0500;
6481

65-
stack_build_string(&state, 0);
82+
stack_build_string(&state, -1);
6683

6784
ot_assign_ref_array(vm, lv_values->ptr, state.values, 0, 0);
6885
ot_set_return_val(vm, &ret);
6986
return 1;
87+
}
88+
89+
int WINAPI filter(LPEXCEPTION_POINTERS ptrs){
90+
if (last_vm!=NULL){
91+
wchar_t buffer[4096];
92+
callback_state state;
93+
*buffer=0;
94+
state.trace = buffer;
95+
state.values = NULL;
96+
state.vm = last_vm;
97+
state.index = 0;
98+
state.group_name=NULL;
99+
100+
void *stack_list = GET_STACKLIST(last_vm);
101+
shlist_traversal(stack_list, &state, callback);
102+
stack_build_string(&state, -1);
103+
MessageBoxW(NULL, buffer, L"Unexpected GPF", MB_OK);
104+
}
105+
return EXCEPTION_EXECUTE_HANDLER;
106+
}
107+
108+
void Install_Crash_Hook(){
109+
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)filter);
110+
}
111+
112+
void Uninstall_Crash_Hook(){
113+
SetUnhandledExceptionFilter(NULL);
70114
}

0 commit comments

Comments
 (0)