[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Libunwind-devel] patch to break out of loop when dwarf_step and is_sign
From: |
dave lerner |
Subject: |
[Libunwind-devel] patch to break out of loop when dwarf_step and is_signal_frame fail on x86 |
Date: |
Thu, 7 Mar 2013 12:25:19 -0600 |
Thanks to all the developers for the work on this well designed, implemented,
and usefull package.
I have an issue and proposed fixed attached below with the x86 frame based
signal unwinder. Hans Boehm seems like a likely reviewer.
Sorry in advance if the format is not correct.
Dave Lerner
-----------------------------------------------------------------
Break out of loop when dwarf_step and is_signal_frame fail on x86
On an x86 target, unw_step returns 1, 'success', even though the
dwarf_step, unw_is_signal_frame and unw_handle_signal_frame each
fail. The cursor is not updated, so that unw_step callers never
exit their loop. This was observed for x86 when the libunwind api
was called from a function with the dll __attribute__((constructor))
tag.
In this case, in unw_step, a bad cfa address causes dwarf_step
to fail. Unw_step calls unw_is_signal_frame which calls access_mem
which also fails probing the bad address. That function's negative
valued return, is returned by unw_is_signal_frame. But the non-0 return,
drops unw_step into the block to call causes unw_handle_signal_frame to
handle the frame and adjust the cursor. The bad address causes
unw_handle_signal_frame to also fail, but that function returns 0 on
failure. Unw_step handles the 0 from unw_handle_signal_frame by
returning 1, 'success' to the caller although the cursor was not
updated by the the signal frame handler.
The patch addresses the problem of a very bad address by changing
unw_step to return the negative return value when unw_is_signal_frame
returns that error value.
Signed-off-by: Dave Lerner <address@hidden>
diff --git a/src/x86/Gos-linux.c b/src/x86/Gos-linux.c
index 31f83ba..0bc390c 100644
--- a/src/x86/Gos-linux.c
+++ b/src/x86/Gos-linux.c
@@ -57,10 +57,11 @@ unw_is_signal_frame (unw_cursor_t *cursor)
if SA_SIGINFO is specified.
*/
ip = c->dwarf.ip;
- if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0
- || (ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0)
- return ret;
- ret = ((w0 == 0x0077b858 && w1 == 0x80cd0000)
+ if ( (*a->access_mem) (as, ip, &w0, 0, arg) < 0
+ || (*a->access_mem) (as, ip + 4, &w1, 0, arg) < 0)
+ ret = 0;
+ else
+ ret = ((w0 == 0x0077b858 && w1 == 0x80cd0000)
|| (w0 == 0x0000adb8 && (w1 & 0xffffff) == 0x80cd00));
Debug (16, "returning %d\n", ret);
return ret;
- [Libunwind-devel] patch to break out of loop when dwarf_step and is_signal_frame fail on x86,
dave lerner <=