|
@@ -1943,23 +1943,30 @@ EXPORT_SYMBOL(unw_unwind);
|
|
int
|
|
int
|
|
unw_unwind_to_user (struct unw_frame_info *info)
|
|
unw_unwind_to_user (struct unw_frame_info *info)
|
|
{
|
|
{
|
|
- unsigned long ip, sp;
|
|
|
|
|
|
+ unsigned long ip, sp, pr = 0;
|
|
|
|
|
|
while (unw_unwind(info) >= 0) {
|
|
while (unw_unwind(info) >= 0) {
|
|
- if (unw_get_rp(info, &ip) < 0) {
|
|
|
|
- unw_get_ip(info, &ip);
|
|
|
|
- UNW_DPRINT(0, "unwind.%s: failed to read return pointer (ip=0x%lx)\n",
|
|
|
|
- __FUNCTION__, ip);
|
|
|
|
- return -1;
|
|
|
|
- }
|
|
|
|
unw_get_sp(info, &sp);
|
|
unw_get_sp(info, &sp);
|
|
- if (sp >= (unsigned long)info->task + IA64_STK_OFFSET)
|
|
|
|
|
|
+ if ((long)((unsigned long)info->task + IA64_STK_OFFSET - sp)
|
|
|
|
+ < IA64_PT_REGS_SIZE) {
|
|
|
|
+ UNW_DPRINT(0, "unwind.%s: ran off the top of the kernel stack\n",
|
|
|
|
+ __FUNCTION__);
|
|
break;
|
|
break;
|
|
- if (ip < FIXADDR_USER_END)
|
|
|
|
|
|
+ }
|
|
|
|
+ if (unw_is_intr_frame(info) &&
|
|
|
|
+ (pr & (1UL << PRED_USER_STACK)))
|
|
return 0;
|
|
return 0;
|
|
|
|
+ if (unw_get_pr (info, &pr) < 0) {
|
|
|
|
+ unw_get_rp(info, &ip);
|
|
|
|
+ UNW_DPRINT(0, "unwind.%s: failed to read "
|
|
|
|
+ "predicate register (ip=0x%lx)\n",
|
|
|
|
+ __FUNCTION__, ip);
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
unw_get_ip(info, &ip);
|
|
unw_get_ip(info, &ip);
|
|
- UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", __FUNCTION__, ip);
|
|
|
|
|
|
+ UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n",
|
|
|
|
+ __FUNCTION__, ip);
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(unw_unwind_to_user);
|
|
EXPORT_SYMBOL(unw_unwind_to_user);
|