LoongArch: Add USER_STACKTRACE support
To get the best stacktrace output, you can compile your userspace programs with frame pointers (at least glibc + the app you are tracing). 1, export "CC = gcc -fno-omit-frame-pointer"; 2, compile your programs with "CC"; 3, use uprobe to get stacktrace output. ... echo 'p:malloc /usr/lib64/libc.so.6:0x0a4704 size=%r4:u64' > uprobe_events echo 'p:free /usr/lib64/libc.so.6:0x0a4d50 ptr=%r4:x64' >> uprobe_events echo 'comm == "demo"' > ./events/uprobes/malloc/filter echo 'comm == "demo"' > ./events/uprobes/free/filter echo 1 > ./options/userstacktrace echo 1 > ./options/sym-userobj ... Signed-off-by: Qing Zhang <zhangqing@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
This commit is contained in:
Родитель
93a4fa622e
Коммит
4d7bf939df
|
@ -119,6 +119,7 @@ config LOONGARCH
|
|||
select SWIOTLB
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
select USE_PERCPU_NUMA_NODE_ID
|
||||
select USER_STACKTRACE_SUPPORT
|
||||
select ZONE_DMA32
|
||||
|
||||
config 32BIT
|
||||
|
|
|
@ -21,6 +21,11 @@ struct stack_info {
|
|||
unsigned long begin, end, next_sp;
|
||||
};
|
||||
|
||||
struct stack_frame {
|
||||
unsigned long fp;
|
||||
unsigned long ra;
|
||||
};
|
||||
|
||||
bool in_irq_stack(unsigned long stack, struct stack_info *info);
|
||||
bool in_task_stack(unsigned long stack, struct task_struct *task, struct stack_info *info);
|
||||
int get_stack_info(unsigned long stack, struct task_struct *task, struct stack_info *info);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
#include <linux/sched.h>
|
||||
#include <linux/stacktrace.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <asm/stacktrace.h>
|
||||
#include <asm/unwind.h>
|
||||
|
@ -35,3 +36,43 @@ void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
copy_stack_frame(unsigned long fp, struct stack_frame *frame)
|
||||
{
|
||||
int ret = 1;
|
||||
unsigned long err;
|
||||
unsigned long __user *user_frame_tail;
|
||||
|
||||
user_frame_tail = (unsigned long *)(fp - sizeof(struct stack_frame));
|
||||
if (!access_ok(user_frame_tail, sizeof(*frame)))
|
||||
return 0;
|
||||
|
||||
pagefault_disable();
|
||||
err = (__copy_from_user_inatomic(frame, user_frame_tail, sizeof(*frame)));
|
||||
if (err || (unsigned long)user_frame_tail >= frame->fp)
|
||||
ret = 0;
|
||||
pagefault_enable();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
|
||||
const struct pt_regs *regs)
|
||||
{
|
||||
unsigned long fp = regs->regs[22];
|
||||
|
||||
while (fp && !((unsigned long)fp & 0xf)) {
|
||||
struct stack_frame frame;
|
||||
|
||||
frame.fp = 0;
|
||||
frame.ra = 0;
|
||||
if (!copy_stack_frame(fp, &frame))
|
||||
break;
|
||||
if (!frame.ra)
|
||||
break;
|
||||
if (!consume_entry(cookie, frame.ra))
|
||||
break;
|
||||
fp = frame.fp;
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче