Issue 4809: Help the stack walker to find the location of a throw statement #80

Merged
merged 1 commit into from Jul 8, 2012
Jump to file or symbol
Failed to load files and symbols.
+25 −0
Diff settings

Always

Just for now

View
@@ -593,15 +593,40 @@ int _d_exception_filter(EXCEPTION_POINTERS *eptrs,
extern(C)
void _d_throwc(Object h)
{
+ // create a standard stack frame, so walking the stack is possible
+ asm
+ {
+ naked;
+ push EBP;
+ mov EBP,ESP;

This comment has been minimized.

@andralex

andralex Jul 8, 2012

Member

space after comma :o)

@andralex

andralex Jul 8, 2012

Member

space after comma :o)

+ }
// @@@ TODO @@@ Signature should change: h will always be a Throwable.
//printf("_d_throw(h = %p, &h = %p)\n", h, &h);
//printf("\tvptr = %p\n", *(void **)h);
_d_createTrace(h);
+
+ // add some space on the stack to allow the stack walker to resynchronize
+ // even without symbols for kernel32/kernelbase.dll
+ asm
+ {
+ mov EAX, 1000;
+ clear_stack:
+ push 0;
+ dec EAX;
+ jnz clear_stack;
+ }
+

This comment has been minimized.

@MartinNowak

MartinNowak Jan 25, 2012

Member

What's the reasoning for this?

@MartinNowak

MartinNowak Jan 25, 2012

Member

What's the reasoning for this?

This comment has been minimized.

@rainers

rainers Jan 25, 2012

Member

What's the reasoning for this?

Without full debug information (including symbols from the Microsoft
symbol sever) the stack walker used by the stack tracing and the
debugger often misses the function on the stack that actually invokes
_d_throw.
My guess is: as there is usually no debug info for both the system DLLs
involved and the D runtime library, the stack walker finds the calling
function by searching addresses on the stack that point to possible code
segments, but somehow skips the missing return address.
The patch fills the stack with zeroes to resynchronize the stack walker,
assuming it starts simply scanning the stack when it it finds a block of
zeroes.

@rainers

rainers Jan 25, 2012

Member

What's the reasoning for this?

Without full debug information (including symbols from the Microsoft
symbol sever) the stack walker used by the stack tracing and the
debugger often misses the function on the stack that actually invokes
_d_throw.
My guess is: as there is usually no debug info for both the system DLLs
involved and the D runtime library, the stack walker finds the calling
function by searching addresses on the stack that point to possible code
segments, but somehow skips the missing return address.
The patch fills the stack with zeroes to resynchronize the stack walker,
assuming it starts simply scanning the stack when it it finds a block of
zeroes.

This comment has been minimized.

@MartinNowak

MartinNowak Jan 25, 2012

Member

Why scanning? StackWalk64 could do normal return address/frame pointer unwinding.
You can try to instrument the ReadMemoryRoutine parameter of StackWalk64 to trace
why this fails.

@MartinNowak

MartinNowak Jan 25, 2012

Member

Why scanning? StackWalk64 could do normal return address/frame pointer unwinding.
You can try to instrument the ReadMemoryRoutine parameter of StackWalk64 to trace
why this fails.

This comment has been minimized.

@rainers

rainers Jan 25, 2012

Member

There are often no frame pointers, so the stack walker only works
correctly with debug info that has frame pointer omission info.

I wasn't aware of the read callback, it might give a hint to improve the
patch...

@rainers

rainers Jan 25, 2012

Member

There are often no frame pointers, so the stack walker only works
correctly with debug info that has frame pointer omission info.

I wasn't aware of the read callback, it might give a hint to improve the
patch...

//_d_setUnhandled(h);
RaiseException(STATUS_DIGITAL_MARS_D_EXCEPTION,
EXCEPTION_NONCONTINUABLE,
1, cast(void *)&h);
+
+ asm
+ {
+ mov ESP,EBP;

This comment has been minimized.

@andralex

andralex Jul 8, 2012

Member

ditto

@andralex

andralex Jul 8, 2012

Member

ditto

+ pop EBP;
+ }
}
/***********************************