aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/unwind.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/kernel/unwind.c')
-rw-r--r--arch/ia64/kernel/unwind.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
index b0b08b5f3eca..c1bdb5131814 100644
--- a/arch/ia64/kernel/unwind.c
+++ b/arch/ia64/kernel/unwind.c
@@ -1856,11 +1856,19 @@ find_save_locs (struct unw_frame_info *info)
1856 return 0; 1856 return 0;
1857} 1857}
1858 1858
1859static int
1860unw_valid(const struct unw_frame_info *info, unsigned long* p)
1861{
1862 unsigned long loc = (unsigned long)p;
1863 return (loc >= info->regstk.limit && loc < info->regstk.top) ||
1864 (loc >= info->memstk.top && loc < info->memstk.limit);
1865}
1866
1859int 1867int
1860unw_unwind (struct unw_frame_info *info) 1868unw_unwind (struct unw_frame_info *info)
1861{ 1869{
1862 unsigned long prev_ip, prev_sp, prev_bsp; 1870 unsigned long prev_ip, prev_sp, prev_bsp;
1863 unsigned long ip, pr, num_regs, rp_loc, pfs_loc; 1871 unsigned long ip, pr, num_regs;
1864 STAT(unsigned long start, flags;) 1872 STAT(unsigned long start, flags;)
1865 int retval; 1873 int retval;
1866 1874
@@ -1871,8 +1879,7 @@ unw_unwind (struct unw_frame_info *info)
1871 prev_bsp = info->bsp; 1879 prev_bsp = info->bsp;
1872 1880
1873 /* validate the return IP pointer */ 1881 /* validate the return IP pointer */
1874 rp_loc = (unsigned long) info->rp_loc; 1882 if (!unw_valid(info, info->rp_loc)) {
1875 if ((rp_loc < info->regstk.limit) || (rp_loc > info->regstk.top)) {
1876 /* FIXME: should really be level 0 but it occurs too often. KAO */ 1883 /* FIXME: should really be level 0 but it occurs too often. KAO */
1877 UNW_DPRINT(1, "unwind.%s: failed to locate return link (ip=0x%lx)!\n", 1884 UNW_DPRINT(1, "unwind.%s: failed to locate return link (ip=0x%lx)!\n",
1878 __FUNCTION__, info->ip); 1885 __FUNCTION__, info->ip);
@@ -1888,8 +1895,7 @@ unw_unwind (struct unw_frame_info *info)
1888 } 1895 }
1889 1896
1890 /* validate the previous stack frame pointer */ 1897 /* validate the previous stack frame pointer */
1891 pfs_loc = (unsigned long) info->pfs_loc; 1898 if (!unw_valid(info, info->pfs_loc)) {
1892 if ((pfs_loc < info->regstk.limit) || (pfs_loc > info->regstk.top)) {
1893 UNW_DPRINT(0, "unwind.%s: failed to locate ar.pfs!\n", __FUNCTION__); 1899 UNW_DPRINT(0, "unwind.%s: failed to locate ar.pfs!\n", __FUNCTION__);
1894 STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); 1900 STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
1895 return -1; 1901 return -1;