diff options
| -rw-r--r-- | arch/ia64/kernel/unwind.c | 16 |
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 | ||
| 1859 | static int | ||
| 1860 | unw_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 | |||
| 1859 | int | 1867 | int |
| 1860 | unw_unwind (struct unw_frame_info *info) | 1868 | unw_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; |
