Skip to content

Commit

Permalink
LoongArch: Add USER_STACKTRACE support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
zhangqingmy authored and chenhuacai committed Aug 12, 2022
1 parent 93a4fa6 commit 4d7bf93
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 0 deletions.
1 change: 1 addition & 0 deletions arch/loongarch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions arch/loongarch/include/asm/stacktrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
41 changes: 41 additions & 0 deletions arch/loongarch/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
#include <linux/sched.h>
#include <linux/stacktrace.h>
#include <linux/uaccess.h>

#include <asm/stacktrace.h>
#include <asm/unwind.h>
Expand Down Expand Up @@ -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;
}
}

0 comments on commit 4d7bf93

Please sign in to comment.