#include <asm/stack_pointer.h>
#include <asm/stacktrace.h>
+enum kunwind_source {
+ KUNWIND_SOURCE_UNKNOWN,
+ KUNWIND_SOURCE_FRAME,
+ KUNWIND_SOURCE_CALLER,
+ KUNWIND_SOURCE_TASK,
+ KUNWIND_SOURCE_REGS_PC,
+};
+
/*
* Kernel unwind state
*
#ifdef CONFIG_KRETPROBES
struct llist_node *kr_cur;
#endif
+ enum kunwind_source source;
};
static __always_inline void
{
unwind_init_common(&state->common);
state->task = task;
+ state->source = KUNWIND_SOURCE_UNKNOWN;
}
/*
state->common.fp = regs->regs[29];
state->common.pc = regs->pc;
+ state->source = KUNWIND_SOURCE_REGS_PC;
}
/*
state->common.fp = (unsigned long)__builtin_frame_address(1);
state->common.pc = (unsigned long)__builtin_return_address(0);
+ state->source = KUNWIND_SOURCE_CALLER;
}
/*
state->common.fp = thread_saved_fp(task);
state->common.pc = thread_saved_pc(task);
+ state->source = KUNWIND_SOURCE_TASK;
}
static __always_inline int
if (fp == (unsigned long)&task_pt_regs(tsk)->stackframe)
return -ENOENT;
- err = unwind_next_frame_record(&state->common);
- if (err)
- return err;
+ switch (state->source) {
+ case KUNWIND_SOURCE_FRAME:
+ case KUNWIND_SOURCE_CALLER:
+ case KUNWIND_SOURCE_TASK:
+ case KUNWIND_SOURCE_REGS_PC:
+ err = unwind_next_frame_record(&state->common);
+ if (err)
+ return err;
+ state->source = KUNWIND_SOURCE_FRAME;
+ break;
+ default:
+ return -EINVAL;
+ }
state->common.pc = ptrauth_strip_kernel_insn_pac(state->common.pc);
kunwind_stack_walk(arch_bpf_unwind_consume_entry, &data, current, NULL);
}
+static const char *state_source_string(const struct kunwind_state *state)
+{
+ switch (state->source) {
+ case KUNWIND_SOURCE_FRAME: return NULL;
+ case KUNWIND_SOURCE_CALLER: return "C";
+ case KUNWIND_SOURCE_TASK: return "T";
+ case KUNWIND_SOURCE_REGS_PC: return "P";
+ default: return "U";
+ }
+}
+
static bool dump_backtrace_entry(const struct kunwind_state *state, void *arg)
{
+ const char *source = state_source_string(state);
char *loglvl = arg;
- printk("%s %pSb\n", loglvl, (void *)state->common.pc);
+ printk("%s %pSb%s%s%s\n", loglvl,
+ (void *)state->common.pc,
+ source ? " (" : "",
+ source ? source : "",
+ source ? ")" : "");
return true;
}