staticvoid notrace walk_stackframe(struct stackframe *fr, struct perf_callchain_entry_ctx *entry)
{ do {
perf_callchain_store(entry, fr->lr);
} while (unwind_frame_kernel(fr) >= 0);
}
/* * Get the return address for a single stackframe and return a pointer to the * next frame tail.
*/ staticunsignedlong user_backtrace(struct perf_callchain_entry_ctx *entry, unsignedlong fp, unsignedlong reg_lr)
{ struct stackframe buftail; unsignedlong lr = 0; unsignedlong __user *user_frame_tail = (unsignedlong __user *)fp;
/* Check accessibility of one struct frame_tail beyond */ if (!access_ok(user_frame_tail, sizeof(buftail))) return 0; if (__copy_from_user_inatomic(&buftail, user_frame_tail, sizeof(buftail))) return 0;
if (reg_lr != 0)
lr = reg_lr; else
lr = buftail.lr;
fp = buftail.fp;
perf_callchain_store(entry, lr);
return fp;
}
/* * This will be called when the target is in user mode * This function will only be called when we use * "PERF_SAMPLE_CALLCHAIN" in * kernel/events/core.c:perf_prepare_sample() * * How to trigger perf_callchain_[user/kernel] : * $ perf record -e cpu-clock --call-graph fp ./program * $ perf report --call-graph * * On C-SKY platform, the program being sampled and the C library * need to be compiled with * -mbacktrace, otherwise the user * stack will not contain function frame.
*/ void perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
{ unsignedlong fp = 0;
/* * While backtrace from leaf function, lr is normally * not saved inside frame on C-SKY, so get lr from pt_regs * at the sample point. However, lr value can be incorrect if * lr is used as temp register
*/
fp = user_backtrace(entry, fp, regs->lr);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.