Commit 259d66a9 authored by David Mosberger's avatar David Mosberger

ia64; Improve debug output from kernel unwinder. Based on patch by

	Keith Owens.
parent 9f319191
...@@ -51,18 +51,24 @@ ...@@ -51,18 +51,24 @@
#define UNW_LOG_HASH_SIZE (UNW_LOG_CACHE_SIZE + 1) #define UNW_LOG_HASH_SIZE (UNW_LOG_CACHE_SIZE + 1)
#define UNW_HASH_SIZE (1 << UNW_LOG_HASH_SIZE) #define UNW_HASH_SIZE (1 << UNW_LOG_HASH_SIZE)
#define UNW_DEBUG 0
#define UNW_STATS 0 /* WARNING: this disabled interrupts for long time-spans!! */ #define UNW_STATS 0 /* WARNING: this disabled interrupts for long time-spans!! */
#if UNW_DEBUG #ifdef UNW_DEBUG
static long unw_debug_level = 255; static unsigned int unw_debug_level = UNW_DEBUG;
# define debug(level,format...) if (unw_debug_level > level) printk(format) # ifdef CONFIG_KDB
# define dprintk(format...) printk(format) # include <linux/kdb.h>
# define UNW_DEBUG_ON(n) (unw_debug_level >= n && !KDB_IS_RUNNING())
# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) kdb_printf(__VA_ARGS__)
# else /* !CONFIG_KDB */
# define UNW_DEBUG_ON(n) unw_debug_level >= n
/* Do not code a printk level, not all debug lines end in newline */
# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__)
# endif /* CONFIG_KDB */
# define inline # define inline
#else #else /* !UNW_DEBUG */
# define debug(level,format...) # define UNW_DEBUG_ON(n) 0
# define dprintk(format...) # define UNW_DPRINT(n, ...)
#endif #endif /* UNW_DEBUG */
#if UNW_STATS #if UNW_STATS
# define STAT(x...) x # define STAT(x...) x
...@@ -111,7 +117,7 @@ static struct { ...@@ -111,7 +117,7 @@ static struct {
/* script cache: */ /* script cache: */
struct unw_script cache[UNW_CACHE_SIZE]; struct unw_script cache[UNW_CACHE_SIZE];
# if UNW_DEBUG # ifdef UNW_DEBUG
const char *preg_name[UNW_NUM_REGS]; const char *preg_name[UNW_NUM_REGS];
# endif # endif
# if UNW_STATS # if UNW_STATS
...@@ -190,7 +196,7 @@ static struct { ...@@ -190,7 +196,7 @@ static struct {
struct_offset(struct unw_frame_info, fr_loc[31 - 16])/8, struct_offset(struct unw_frame_info, fr_loc[31 - 16])/8,
}, },
.hash = { [0 ... UNW_HASH_SIZE - 1] = -1 }, .hash = { [0 ... UNW_HASH_SIZE - 1] = -1 },
#if UNW_DEBUG #ifdef UNW_DEBUG
.preg_name = { .preg_name = {
"pri_unat_gr", "pri_unat_mem", "bsp", "bspstore", "ar.pfs", "ar.rnat", "psp", "rp", "pri_unat_gr", "pri_unat_mem", "bsp", "bspstore", "ar.pfs", "ar.rnat", "psp", "rp",
"r4", "r5", "r6", "r7", "r4", "r5", "r6", "r7",
...@@ -223,7 +229,7 @@ pt_regs_off (unsigned long reg) ...@@ -223,7 +229,7 @@ pt_regs_off (unsigned long reg)
else if (reg <= 31) else if (reg <= 31)
off = struct_offset(struct pt_regs, r16) + 8*(reg - 16); off = struct_offset(struct pt_regs, r16) + 8*(reg - 16);
else else
dprintk("unwind: bad scratch reg r%lu\n", reg); UNW_DPRINT(0, "unwind.%s: bad scratch reg r%lu\n", __FUNCTION__, reg);
return off; return off;
} }
...@@ -232,9 +238,12 @@ dump_info_pt(struct unw_frame_info *info, const char *func) ...@@ -232,9 +238,12 @@ dump_info_pt(struct unw_frame_info *info, const char *func)
{ {
/* WAR for no struct pt_regs, may be caused by bad unwind data. KAO */ /* WAR for no struct pt_regs, may be caused by bad unwind data. KAO */
if (!info->pt) { if (!info->pt) {
dprintk("unwind.%s: sp 0x%lx pt 0x%lx, set to 0x%lx\n", func, info->sp, info->pt, info->sp - 16); UNW_DPRINT(0, "unwind.%s: sp 0x%lx pt 0x%lx, set to 0x%lx\n", func, info->sp, info->pt, info->sp - 16);
info->pt = info->sp - 16; info->pt = info->sp - 16;
} }
else {
UNW_DPRINT(3, "unwind.%s: sp 0x%lx pt 0x%lx\n", func, info->sp, info->pt);
}
} }
int int
...@@ -244,7 +253,7 @@ unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char ...@@ -244,7 +253,7 @@ unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char
struct unw_ireg *ireg; struct unw_ireg *ireg;
if ((unsigned) regnum - 1 >= 127) { if ((unsigned) regnum - 1 >= 127) {
dprintk("unwind: trying to access non-existent r%u\n", regnum); UNW_DPRINT(0, "unwind.%s: trying to access non-existent r%u\n", __FUNCTION__, regnum);
return -1; return -1;
} }
...@@ -289,8 +298,9 @@ unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char ...@@ -289,8 +298,9 @@ unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char
if ((unsigned long) addr < info->regstk.limit if ((unsigned long) addr < info->regstk.limit
|| (unsigned long) addr >= info->regstk.top) || (unsigned long) addr >= info->regstk.top)
{ {
dprintk("unwind: %p outside of regstk " UNW_DPRINT(0, "unwind.%s: %p outside of regstk "
"[0x%lx-0x%lx)\n", (void *) addr, "[0x%lx-0x%lx)\n",
__FUNCTION__, (void *) addr,
info->regstk.limit, info->regstk.limit,
info->regstk.top); info->regstk.top);
return -1; return -1;
...@@ -322,7 +332,7 @@ unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char ...@@ -322,7 +332,7 @@ unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char
if ((unsigned long) addr < info->regstk.limit if ((unsigned long) addr < info->regstk.limit
|| (unsigned long) addr >= info->regstk.top) || (unsigned long) addr >= info->regstk.top)
{ {
dprintk("unwind: ignoring attempt to access register outside of rbs\n"); UNW_DPRINT(0, "unwind.%s: ignoring attempt to access register outside of rbs\n", __FUNCTION__);
return -1; return -1;
} }
if ((unsigned long) nat_addr >= info->regstk.top) if ((unsigned long) nat_addr >= info->regstk.top)
...@@ -370,7 +380,7 @@ unw_access_br (struct unw_frame_info *info, int regnum, unsigned long *val, int ...@@ -370,7 +380,7 @@ unw_access_br (struct unw_frame_info *info, int regnum, unsigned long *val, int
break; break;
default: default:
dprintk("unwind: trying to access non-existent b%u\n", regnum); UNW_DPRINT(0, "unwind.%s: trying to access non-existent b%u\n", __FUNCTION__, regnum);
return -1; return -1;
} }
if (write) if (write)
...@@ -387,7 +397,7 @@ unw_access_fr (struct unw_frame_info *info, int regnum, struct ia64_fpreg *val, ...@@ -387,7 +397,7 @@ unw_access_fr (struct unw_frame_info *info, int regnum, struct ia64_fpreg *val,
struct pt_regs *pt; struct pt_regs *pt;
if ((unsigned) (regnum - 2) >= 126) { if ((unsigned) (regnum - 2) >= 126) {
dprintk("unwind: trying to access non-existent f%u\n", regnum); UNW_DPRINT(0, "unwind.%s: trying to access non-existent f%u\n", __FUNCTION__, regnum);
return -1; return -1;
} }
...@@ -495,7 +505,7 @@ unw_access_ar (struct unw_frame_info *info, int regnum, unsigned long *val, int ...@@ -495,7 +505,7 @@ unw_access_ar (struct unw_frame_info *info, int regnum, unsigned long *val, int
break; break;
default: default:
dprintk("unwind: trying to access non-existent ar%u\n", regnum); UNW_DPRINT(0, "unwind.%s: trying to access non-existent ar%u\n", __FUNCTION__, regnum);
return -1; return -1;
} }
...@@ -612,7 +622,7 @@ decode_abreg (unsigned char abreg, int memory) ...@@ -612,7 +622,7 @@ decode_abreg (unsigned char abreg, int memory)
default: default:
break; break;
} }
dprintk("unwind: bad abreg=0x%x\n", abreg); UNW_DPRINT(0, "unwind.%s: bad abreg=0x%x\n", __FUNCTION__, abreg);
return UNW_REG_LC; return UNW_REG_LC;
} }
...@@ -652,7 +662,7 @@ spill_next_when (struct unw_reg_info **regp, struct unw_reg_info *lim, unw_word ...@@ -652,7 +662,7 @@ spill_next_when (struct unw_reg_info **regp, struct unw_reg_info *lim, unw_word
return; return;
} }
} }
dprintk("unwind: excess spill!\n"); UNW_DPRINT(0, "unwind.%s: excess spill!\n", __FUNCTION__);
} }
static inline void static inline void
...@@ -765,10 +775,13 @@ desc_prologue (int body, unw_word rlen, unsigned char mask, unsigned char grsave ...@@ -765,10 +775,13 @@ desc_prologue (int body, unw_word rlen, unsigned char mask, unsigned char grsave
static inline void static inline void
desc_abi (unsigned char abi, unsigned char context, struct unw_state_record *sr) desc_abi (unsigned char abi, unsigned char context, struct unw_state_record *sr)
{ {
if (abi == 0 && context == 'i') if (abi == 0 && context == 'i') {
sr->flags |= UNW_FLAG_INTERRUPT_FRAME; sr->flags |= UNW_FLAG_INTERRUPT_FRAME;
UNW_DPRINT(3, "unwind.%s: interrupt frame\n", __FUNCTION__);
}
else else
dprintk("unwind: ignoring unwabi(abi=0x%x,context=0x%x)\n", abi, context); UNW_DPRINT(0, "unwind%s: ignoring unwabi(abi=0x%x,context=0x%x)\n",
__FUNCTION__, abi, context);
} }
static inline void static inline void
...@@ -1136,6 +1149,9 @@ script_lookup (struct unw_frame_info *info) ...@@ -1136,6 +1149,9 @@ script_lookup (struct unw_frame_info *info)
unsigned short index; unsigned short index;
unsigned long ip, pr; unsigned long ip, pr;
if (UNW_DEBUG_ON(0))
return 0; /* Always regenerate scripts in debug mode */
STAT(++unw.stat.cache.lookups); STAT(++unw.stat.cache.lookups);
ip = info->ip; ip = info->ip;
...@@ -1260,8 +1276,8 @@ static inline void ...@@ -1260,8 +1276,8 @@ static inline void
script_emit (struct unw_script *script, struct unw_insn insn) script_emit (struct unw_script *script, struct unw_insn insn)
{ {
if (script->count >= UNW_MAX_SCRIPT_LEN) { if (script->count >= UNW_MAX_SCRIPT_LEN) {
dprintk("unwind: script exceeds maximum size of %u instructions!\n", UNW_DPRINT(0, "unwind.%s: script exceeds maximum size of %u instructions!\n",
UNW_MAX_SCRIPT_LEN); __FUNCTION__, UNW_MAX_SCRIPT_LEN);
return; return;
} }
script->insn[script->count++] = insn; script->insn[script->count++] = insn;
...@@ -1302,7 +1318,7 @@ emit_nat_info (struct unw_state_record *sr, int i, struct unw_script *script) ...@@ -1302,7 +1318,7 @@ emit_nat_info (struct unw_state_record *sr, int i, struct unw_script *script)
break; break;
default: default:
dprintk("unwind: don't know how to emit nat info for where = %u\n", r->where); UNW_DPRINT(0, "unwind.%s: don't know how to emit nat info for where = %u\n", __FUNCTION__, r->where);
return; return;
} }
insn.opc = opc; insn.opc = opc;
...@@ -1355,7 +1371,7 @@ compile_reg (struct unw_state_record *sr, int i, struct unw_script *script) ...@@ -1355,7 +1371,7 @@ compile_reg (struct unw_state_record *sr, int i, struct unw_script *script)
if (rval <= 9) if (rval <= 9)
val = struct_offset(struct pt_regs, f6) + 16*(rval - 6); val = struct_offset(struct pt_regs, f6) + 16*(rval - 6);
else else
dprintk("unwind: kernel may not touch f%lu\n", rval); UNW_DPRINT(0, "unwind.%s: kernel may not touch f%lu\n", __FUNCTION__, rval);
} }
break; break;
...@@ -1382,7 +1398,7 @@ compile_reg (struct unw_state_record *sr, int i, struct unw_script *script) ...@@ -1382,7 +1398,7 @@ compile_reg (struct unw_state_record *sr, int i, struct unw_script *script)
break; break;
default: default:
dprintk("unwind: register %u has unexpected `where' value of %u\n", i, r->where); UNW_DPRINT(0, "unwind%s: register %u has unexpected `where' value of %u\n", __FUNCTION__, i, r->where);
break; break;
} }
insn.opc = opc; insn.opc = opc;
...@@ -1455,9 +1471,10 @@ build_script (struct unw_frame_info *info) ...@@ -1455,9 +1471,10 @@ build_script (struct unw_frame_info *info)
r->when = UNW_WHEN_NEVER; r->when = UNW_WHEN_NEVER;
sr.pr_val = info->pr; sr.pr_val = info->pr;
UNW_DPRINT(3, "unwind.%s: ip 0x%lx\n", __FUNCTION__, ip);
script = script_new(ip); script = script_new(ip);
if (!script) { if (!script) {
dprintk("unwind: failed to create unwind script\n"); UNW_DPRINT(0, "unwind.%s: failed to create unwind script\n", __FUNCTION__);
STAT(unw.stat.script.build_time += ia64_get_itc() - start); STAT(unw.stat.script.build_time += ia64_get_itc() - start);
return 0; return 0;
} }
...@@ -1475,8 +1492,8 @@ build_script (struct unw_frame_info *info) ...@@ -1475,8 +1492,8 @@ build_script (struct unw_frame_info *info)
} }
if (!e) { if (!e) {
/* no info, return default unwinder (leaf proc, no mem stack, no saved regs) */ /* no info, return default unwinder (leaf proc, no mem stack, no saved regs) */
dprintk("unwind: no unwind info for ip=0x%lx (prev ip=0x%lx)\n", ip, UNW_DPRINT(1, "unwind.%s: no unwind info for ip=0x%lx (prev ip=0x%lx)\n",
unw.cache[info->prev_script].ip); __FUNCTION__, ip, unw.cache[info->prev_script].ip);
sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR; sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
sr.curr.reg[UNW_REG_RP].when = -1; sr.curr.reg[UNW_REG_RP].when = -1;
sr.curr.reg[UNW_REG_RP].val = 0; sr.curr.reg[UNW_REG_RP].val = 0;
...@@ -1524,26 +1541,28 @@ build_script (struct unw_frame_info *info) ...@@ -1524,26 +1541,28 @@ build_script (struct unw_frame_info *info)
sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR; sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
sr.curr.reg[UNW_REG_RP].when = -1; sr.curr.reg[UNW_REG_RP].when = -1;
sr.curr.reg[UNW_REG_RP].val = sr.return_link_reg; sr.curr.reg[UNW_REG_RP].val = sr.return_link_reg;
UNW_DPRINT(1, "unwind.%s: using default for rp at ip=0x%lx where=%d val=0x%lx\n",
__FUNCTION__, ip, sr.curr.reg[UNW_REG_RP].where, sr.curr.reg[UNW_REG_RP].val);
} }
#if UNW_DEBUG #ifdef UNW_DEBUG
printk("unwind: state record for func 0x%lx, t=%u:\n", UNW_DPRINT(1, "unwind.%s: state record for func 0x%lx, t=%u:\n",
table->segment_base + e->start_offset, sr.when_target); __FUNCTION__, table->segment_base + e->start_offset, sr.when_target);
for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r) { for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r) {
if (r->where != UNW_WHERE_NONE || r->when != UNW_WHEN_NEVER) { if (r->where != UNW_WHERE_NONE || r->when != UNW_WHEN_NEVER) {
printk(" %s <- ", unw.preg_name[r - sr.curr.reg]); UNW_DPRINT(1, " %s <- ", unw.preg_name[r - sr.curr.reg]);
switch (r->where) { switch (r->where) {
case UNW_WHERE_GR: printk("r%lu", r->val); break; case UNW_WHERE_GR: UNW_DPRINT(1, "r%lu", r->val); break;
case UNW_WHERE_FR: printk("f%lu", r->val); break; case UNW_WHERE_FR: UNW_DPRINT(1, "f%lu", r->val); break;
case UNW_WHERE_BR: printk("b%lu", r->val); break; case UNW_WHERE_BR: UNW_DPRINT(1, "b%lu", r->val); break;
case UNW_WHERE_SPREL: printk("[sp+0x%lx]", r->val); break; case UNW_WHERE_SPREL: UNW_DPRINT(1, "[sp+0x%lx]", r->val); break;
case UNW_WHERE_PSPREL: printk("[psp+0x%lx]", r->val); break; case UNW_WHERE_PSPREL: UNW_DPRINT(1, "[psp+0x%lx]", r->val); break;
case UNW_WHERE_NONE: case UNW_WHERE_NONE:
printk("%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val); UNW_DPRINT(1, "%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val);
break; break;
default: printk("BADWHERE(%d)", r->where); break; default: UNW_DPRINT(1, "BADWHERE(%d)", r->where); break;
} }
printk("\t\t%d\n", r->when); UNW_DPRINT(1, "\t\t%d\n", r->when);
} }
} }
#endif #endif
...@@ -1648,7 +1667,7 @@ run_script (struct unw_script *script, struct unw_frame_info *state) ...@@ -1648,7 +1667,7 @@ run_script (struct unw_script *script, struct unw_frame_info *state)
} }
else { else {
s[dst] = 0; s[dst] = 0;
dprintk("unwind.%s: no state->pt, dst=%ld, val=%ld\n", __FUNCTION__, dst, val); UNW_DPRINT(0, "unwind.%s: no state->pt, dst=%ld, val=%ld\n", __FUNCTION__, dst, val);
} }
break; break;
...@@ -1677,11 +1696,11 @@ run_script (struct unw_script *script, struct unw_frame_info *state) ...@@ -1677,11 +1696,11 @@ run_script (struct unw_script *script, struct unw_frame_info *state)
break; break;
case UNW_INSN_LOAD: case UNW_INSN_LOAD:
#if UNW_DEBUG #ifdef UNW_DEBUG
if ((s[val] & (local_cpu_data->unimpl_va_mask | 0x7)) != 0 if ((s[val] & (local_cpu_data->unimpl_va_mask | 0x7)) != 0
|| s[val] < TASK_SIZE) || s[val] < TASK_SIZE)
{ {
debug(1, "unwind: rejecting bad psp=0x%lx\n", s[val]); UNW_DPRINT(0, "unwind.%s: rejecting bad psp=0x%lx\n", __FUNCTION__, s[val]);
break; break;
} }
#endif #endif
...@@ -1714,7 +1733,8 @@ find_save_locs (struct unw_frame_info *info) ...@@ -1714,7 +1733,8 @@ find_save_locs (struct unw_frame_info *info)
if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf)) || info->ip < TASK_SIZE) { if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf)) || info->ip < TASK_SIZE) {
/* don't let obviously bad addresses pollute the cache */ /* don't let obviously bad addresses pollute the cache */
debug(1, "unwind: rejecting bad ip=0x%lx\n", info->ip); /* FIXME: should really be level 0 but it occurs too often. KAO */
UNW_DPRINT(1, "unwind.%s: rejecting bad ip=0x%lx\n", __FUNCTION__, info->ip);
info->rp_loc = 0; info->rp_loc = 0;
return -1; return -1;
} }
...@@ -1723,8 +1743,8 @@ find_save_locs (struct unw_frame_info *info) ...@@ -1723,8 +1743,8 @@ find_save_locs (struct unw_frame_info *info)
if (!scr) { if (!scr) {
scr = build_script(info); scr = build_script(info);
if (!scr) { if (!scr) {
dprintk("unwind: failed to locate/build unwind script for ip %lx\n", UNW_DPRINT(0, "unwind.%s: failed to locate/build unwind script for ip %lx\n",
info->ip); __FUNCTION__, info->ip);
return -1; return -1;
} }
have_write_lock = 1; have_write_lock = 1;
...@@ -1757,7 +1777,8 @@ unw_unwind (struct unw_frame_info *info) ...@@ -1757,7 +1777,8 @@ unw_unwind (struct unw_frame_info *info)
/* restore the ip */ /* restore the ip */
if (!info->rp_loc) { if (!info->rp_loc) {
debug(1, "unwind: failed to locate return link (ip=0x%lx)!\n", info->ip); /* FIXME: should really be level 0 but it occurs too often. KAO */
UNW_DPRINT(1, "unwind.%s: failed to locate return link (ip=0x%lx)!\n", __FUNCTION__, info->ip);
STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
return -1; return -1;
} }
...@@ -1767,14 +1788,14 @@ unw_unwind (struct unw_frame_info *info) ...@@ -1767,14 +1788,14 @@ unw_unwind (struct unw_frame_info *info)
* We don't have unwind info for the gate page, so we consider that part * We don't have unwind info for the gate page, so we consider that part
* of user-space for the purpose of unwinding. * of user-space for the purpose of unwinding.
*/ */
debug(1, "unwind: reached user-space (ip=0x%lx)\n", ip); UNW_DPRINT(2, "unwind.%s: reached user-space (ip=0x%lx)\n", __FUNCTION__, ip);
STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
return -1; return -1;
} }
/* restore the cfm: */ /* restore the cfm: */
if (!info->pfs_loc) { if (!info->pfs_loc) {
dprintk("unwind: failed to locate ar.pfs!\n"); UNW_DPRINT(0, "unwind.%s: failed to locate ar.pfs!\n", __FUNCTION__);
STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
return -1; return -1;
} }
...@@ -1789,12 +1810,13 @@ unw_unwind (struct unw_frame_info *info) ...@@ -1789,12 +1810,13 @@ unw_unwind (struct unw_frame_info *info)
num_regs = *info->cfm_loc & 0x7f; /* size of frame */ num_regs = *info->cfm_loc & 0x7f; /* size of frame */
info->pfs_loc = info->pfs_loc =
(unsigned long *) (info->pt + struct_offset(struct pt_regs, ar_pfs)); (unsigned long *) (info->pt + struct_offset(struct pt_regs, ar_pfs));
UNW_DPRINT(3, "unwind.%s: interrupt_frame pt 0x%lx\n", __FUNCTION__, info->pt);
} else } else
num_regs = (*info->cfm_loc >> 7) & 0x7f; /* size of locals */ num_regs = (*info->cfm_loc >> 7) & 0x7f; /* size of locals */
info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->bsp, -num_regs); info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->bsp, -num_regs);
if (info->bsp < info->regstk.limit || info->bsp > info->regstk.top) { if (info->bsp < info->regstk.limit || info->bsp > info->regstk.top) {
dprintk("unwind: bsp (0x%lx) out of range [0x%lx-0x%lx]\n", UNW_DPRINT(0, "unwind.%s: bsp (0x%lx) out of range [0x%lx-0x%lx]\n",
info->bsp, info->regstk.limit, info->regstk.top); __FUNCTION__, info->bsp, info->regstk.limit, info->regstk.top);
STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
return -1; return -1;
} }
...@@ -1802,14 +1824,14 @@ unw_unwind (struct unw_frame_info *info) ...@@ -1802,14 +1824,14 @@ unw_unwind (struct unw_frame_info *info)
/* restore the sp: */ /* restore the sp: */
info->sp = info->psp; info->sp = info->psp;
if (info->sp < info->memstk.top || info->sp > info->memstk.limit) { if (info->sp < info->memstk.top || info->sp > info->memstk.limit) {
dprintk("unwind: sp (0x%lx) out of range [0x%lx-0x%lx]\n", UNW_DPRINT(0, "unwind.%s: sp (0x%lx) out of range [0x%lx-0x%lx]\n",
info->sp, info->memstk.top, info->memstk.limit); __FUNCTION__, info->sp, info->memstk.top, info->memstk.limit);
STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
return -1; return -1;
} }
if (info->ip == prev_ip && info->sp == prev_sp && info->bsp == prev_bsp) { if (info->ip == prev_ip && info->sp == prev_sp && info->bsp == prev_bsp) {
dprintk("unwind: ip, sp, bsp remain unchanged; stopping here (ip=0x%lx)\n", ip); UNW_DPRINT(0, "unwind.%s: ip, sp, bsp remain unchanged; stopping here (ip=0x%lx)\n", __FUNCTION__, ip);
STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
return -1; return -1;
} }
...@@ -1833,7 +1855,7 @@ unw_unwind_to_user (struct unw_frame_info *info) ...@@ -1833,7 +1855,7 @@ unw_unwind_to_user (struct unw_frame_info *info)
while (unw_unwind(info) >= 0) { while (unw_unwind(info) >= 0) {
if (unw_get_rp(info, &ip) < 0) { if (unw_get_rp(info, &ip) < 0) {
unw_get_ip(info, &ip); unw_get_ip(info, &ip);
dprintk("unwind: failed to read return pointer (ip=0x%lx)\n", ip); UNW_DPRINT(0, "unwind.%s: failed to read return pointer (ip=0x%lx)\n", __FUNCTION__, ip);
return -1; return -1;
} }
/* /*
...@@ -1844,7 +1866,7 @@ unw_unwind_to_user (struct unw_frame_info *info) ...@@ -1844,7 +1866,7 @@ unw_unwind_to_user (struct unw_frame_info *info)
return 0; return 0;
} }
unw_get_ip(info, &ip); unw_get_ip(info, &ip);
dprintk("unwind: failed to unwind to user-level (ip=0x%lx)\n", ip); UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", __FUNCTION__, ip);
return -1; return -1;
} }
...@@ -1891,6 +1913,24 @@ unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct ...@@ -1891,6 +1913,24 @@ unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct
info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sol); info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sol);
info->ip = sw->b0; info->ip = sw->b0;
info->pr = sw->pr; info->pr = sw->pr;
UNW_DPRINT(3,
"unwind.%s\n"
" rbslimit 0x%lx\n"
" rbstop 0x%lx\n"
" stklimit 0x%lx\n"
" stktop 0x%lx\n"
" task 0x%lx\n"
" sw 0x%lx\n",
__FUNCTION__, rbslimit, rbstop, stklimit, stktop,
(unsigned long)(info->task),
(unsigned long)(info->sw));
UNW_DPRINT(3,
" sp/psp 0x%lx\n"
" sol 0x%lx\n"
" bsp 0x%lx\n"
" ip 0x%lx\n"
" pr 0x%lx\n",
info->sp, sol, info->bsp, info->ip, info->pr);
find_save_locs(info); find_save_locs(info);
STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags)); STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags));
...@@ -1901,6 +1941,7 @@ unw_init_from_blocked_task (struct unw_frame_info *info, struct task_struct *t) ...@@ -1901,6 +1941,7 @@ unw_init_from_blocked_task (struct unw_frame_info *info, struct task_struct *t)
{ {
struct switch_stack *sw = (struct switch_stack *) (t->thread.ksp + 16); struct switch_stack *sw = (struct switch_stack *) (t->thread.ksp + 16);
UNW_DPRINT(1, "unwind.%s\n", __FUNCTION__);
unw_init_frame_info(info, t, sw); unw_init_frame_info(info, t, sw);
} }
...@@ -1928,7 +1969,7 @@ unw_add_unwind_table (const char *name, unsigned long segment_base, unsigned lon ...@@ -1928,7 +1969,7 @@ unw_add_unwind_table (const char *name, unsigned long segment_base, unsigned lon
unsigned long flags; unsigned long flags;
if (end - start <= 0) { if (end - start <= 0) {
dprintk("unwind: ignoring attempt to insert empty unwind table\n"); UNW_DPRINT(0, "unwind.%s: ignoring attempt to insert empty unwind table\n", __FUNCTION__);
return 0; return 0;
} }
...@@ -1958,13 +1999,13 @@ unw_remove_unwind_table (void *handle) ...@@ -1958,13 +1999,13 @@ unw_remove_unwind_table (void *handle)
long index; long index;
if (!handle) { if (!handle) {
dprintk("unwind: ignoring attempt to remove non-existent unwind table\n"); UNW_DPRINT(0, "unwind.%s: ignoring attempt to remove non-existent unwind table\n", __FUNCTION__);
return; return;
} }
table = handle; table = handle;
if (table == &unw.kernel_table) { if (table == &unw.kernel_table) {
dprintk("unwind: sorry, freeing the kernel's unwind table is a no-can-do!\n"); UNW_DPRINT(0, "unwind.%s: sorry, freeing the kernel's unwind table is a no-can-do!\n", __FUNCTION__);
return; return;
} }
...@@ -1976,7 +2017,7 @@ unw_remove_unwind_table (void *handle) ...@@ -1976,7 +2017,7 @@ unw_remove_unwind_table (void *handle)
if (prev->next == table) if (prev->next == table)
break; break;
if (!prev) { if (!prev) {
dprintk("unwind: failed to find unwind table %p\n", (void *) table); UNW_DPRINT(0, "unwind.%s: failed to find unwind table %p\n", __FUNCTION__, (void *) table);
spin_unlock_irqrestore(&unw.lock, flags); spin_unlock_irqrestore(&unw.lock, flags);
return; return;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment