/*
- * Copyright (C) 1999-2003 Hewlett-Packard Co
+ * Copyright (C) 1999-2004 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 2003 Fenghua Yu <fenghua.yu@intel.com>
* - Change pt_regs_off() to make it less dependant on pt_regs structure.
/* list of unwind tables (one per load-module) */
struct unw_table *tables;
+ unsigned long r0; /* constant 0 for r0 */
+
/* table of registers that prologues can save (and order in which they're saved): */
const unsigned char save_order[8];
#endif
};
-/* Unwind accessors. */
+static inline int
+read_only (void *addr)
+{
+ return (unsigned long) ((char *) addr - (char *) &unw.r0) < sizeof(unw.r0);
+}
/*
* Returns offset of rREG in struct pt_regs.
return (struct pt_regs *) info->pt;
}
+/* Unwind accessors. */
+
int
unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char *nat, int write)
{
}
if (write) {
- *addr = *val;
- if (*nat)
- *nat_addr |= nat_mask;
- else
- *nat_addr &= ~nat_mask;
+ if (read_only(addr))
+ UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n");
+ else {
+ *addr = *val;
+ if (*nat)
+ *nat_addr |= nat_mask;
+ else
+ *nat_addr &= ~nat_mask;
+ }
} else {
if ((*nat_addr & nat_mask) == 0) {
*val = *addr;
return -1;
}
if (write)
- *addr = *val;
+ if (read_only(addr))
+ UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n");
+ else
+ *addr = *val;
else
*val = *addr;
return 0;
}
if (write)
- *addr = *val;
+ if (read_only(addr))
+ UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n");
+ else
+ *addr = *val;
else
*val = *addr;
return 0;
return -1;
}
- if (write)
- *addr = *val;
- else
+ if (write) {
+ if (read_only(addr))
+ UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n");
+ else
+ *addr = *val;
+ } else
*val = *addr;
return 0;
}
if (!addr)
addr = &info->sw->pr;
- if (write)
- *addr = *val;
- else
+ if (write) {
+ if (read_only(addr))
+ UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n");
+ else
+ *addr = *val;
+ } else
*val = *addr;
return 0;
}
need_nat_info = 0;
}
val = unw.preg_index[UNW_REG_R4 + (rval - 4)];
+ } else if (rval == 0) {
+ opc = UNW_INSN_MOVE_CONST;
+ val = 0;
} else {
/* register got spilled to a scratch register */
opc = UNW_INSN_MOVE_SCRATCH;
}
break;
+ case UNW_INSN_MOVE_CONST:
+ if (val == 0)
+ s[dst] = (unsigned long) &unw.r0;
+ else {
+ s[dst] = 0;
+ UNW_DPRINT(0, "unwind.%s: UNW_INSN_MOVE_CONST bad val=%ld\n",
+ __FUNCTION__, val);
+ }
+ break;
+
+
case UNW_INSN_MOVE_STACKED:
s[dst] = (unsigned long) ia64_rse_skip_regs((unsigned long *)state->bsp,
val);