|
|
@@ -113,6 +113,20 @@ static struct orc_entry *orc_ftrace_find(unsigned long ip)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+/*
|
|
|
+ * If we crash with IP==0, the last successfully executed instruction
|
|
|
+ * was probably an indirect function call with a NULL function pointer,
|
|
|
+ * and we don't have unwind information for NULL.
|
|
|
+ * This hardcoded ORC entry for IP==0 allows us to unwind from a NULL function
|
|
|
+ * pointer into its parent and then continue normally from there.
|
|
|
+ */
|
|
|
+static struct orc_entry null_orc_entry = {
|
|
|
+ .sp_offset = sizeof(long),
|
|
|
+ .sp_reg = ORC_REG_SP,
|
|
|
+ .bp_reg = ORC_REG_UNDEFINED,
|
|
|
+ .type = ORC_TYPE_CALL
|
|
|
+};
|
|
|
+
|
|
|
static struct orc_entry *orc_find(unsigned long ip)
|
|
|
{
|
|
|
static struct orc_entry *orc;
|
|
|
@@ -120,6 +134,9 @@ static struct orc_entry *orc_find(unsigned long ip)
|
|
|
if (!orc_init)
|
|
|
return NULL;
|
|
|
|
|
|
+ if (ip == 0)
|
|
|
+ return &null_orc_entry;
|
|
|
+
|
|
|
/* For non-init vmlinux addresses, use the fast lookup table: */
|
|
|
if (ip >= LOOKUP_START_IP && ip < LOOKUP_STOP_IP) {
|
|
|
unsigned int idx, start, stop;
|