All of lore.kernel.org
 help / color / mirror / Atom feed
From: Fuxin Zhang <fxzhang@ict.ac.cn>
To: Linux/MIPS Development <linux-mips@linux-mips.org>
Subject: stack backtrace
Date: Sun, 02 Apr 2006 22:38:02 +0800	[thread overview]
Message-ID: <442FE1CA.4030905@ict.ac.cn> (raw)

hi Ralf,

    The dwarf unwinding code is too complex and I have no time to port
it. And I doubt it will be important enough to deserve the space costs,
the -gdwarf-2 kernel is more than 20MB.

    Instead for my need I just hack up a simple version of way 1, with
frame pointer kept on: CONFIG_FRAME_POINTER.

BTW:It seems nobody use this option for MIPS? Is it dangerous? The size
and performance overhead should be barable at most time for debugging?

here is the code patch(just for reference), it depends on
CONFIG_KALLSYMS too.


--- traps.c.orig	2006-04-02 21:39:01.000000000 +0800
+++ traps.c	2006-04-02 22:38:03.000000000 +0800
@@ -116,8 +116,129 @@
 	printk("\n");
 }

-void show_trace(struct task_struct *task, unsigned long *stack)
+#include <asm/inst.h>
+
+static struct mips_frame_info {
+	void *func;
+	int omit_fp;	/* compiled without fno-omit-frame-pointer */
+	int frame_offset;
+	int pc_offset;
+} tmp_frame;
+
+static int get_frame_info(void *func,struct mips_frame_info *info)
+{
+	int i;
+	union mips_instruction *ip = (union mips_instruction *)func;
+	info->pc_offset = -1;
+	info->frame_offset = -1;
+	for (i = 0; i < 128; i++, ip++) {
+		/* if jal, jalr, jr, stop. */
+		if (ip->j_format.opcode == jal_op ||
+		    (ip->r_format.opcode == spec_op &&
+		     (ip->r_format.func == jalr_op ||
+		      ip->r_format.func == jr_op)))
+			break;
+
+		if (
+#ifdef CONFIG_32BIT
+		    ip->i_format.opcode == sw_op &&
+#endif
+#ifdef CONFIG_64BIT
+		    ip->i_format.opcode == sd_op &&
+#endif
+		    ip->i_format.rs == 29)
+		{
+			/* sw / sd $ra, offset($sp) */
+			if (ip->i_format.rt == 31) {
+				if (info->pc_offset != -1)
+					continue;
+				info->pc_offset =
+					ip->i_format.simmediate / sizeof(long);
+			}
+			/* sw / sd $s8, offset($sp) */
+			if (ip->i_format.rt == 30) {
+//#if 0	/* gcc 3.4 does aggressive optimization... */
+				if (info->frame_offset != -1)
+					continue;
+//#endif
+				info->frame_offset =
+					ip->i_format.simmediate / sizeof(long);
+			}
+		}
+	}
+	if (info->pc_offset == -1 || info->frame_offset == -1) {
+		printk("Can't analyze prologue code at %p\n", func);
+		info->pc_offset = -1;
+		info->frame_offset = -1;
+		return -1;
+	}
+
+	return 0;
+}
+
+static void show_trace(struct task_struct *task, void *regs_in)
 {
+	unsigned long prev_sp,stack_top;
+	unsigned long count = 0;
+	unsigned long frame, pc;
+	char namebuf[KSYM_NAME_LEN+1];
+	const char *name;
+	char *modname;
+	unsigned long size,offset;
+	struct pt_regs *regs;
+	int in_exception = 0;
+
+	if (regs_in) /* called from show_registers */
+	  regs = (struct pt_regs*) regs_in;
+	else
+	  regs = (struct pt_regs *) ((unsigned long) task->thread_info +
+	      THREAD_SIZE - 32 - sizeof(struct pt_regs));
+
+	printk("Call Trace:\n");
+
+	prev_sp = (unsigned long) (task->thread_info + 1);
+	stack_top = (unsigned long) task->thread_info + THREAD_SIZE;
+
+	pc = (unsigned long)show_trace;
+
+	if (get_frame_info((void*)pc,&tmp_frame))
+	  return;
+
+	__asm__ volatile ("addu %0,$0,$30" : "=r" (frame));
+
+	do {
+		pc = ((unsigned long *)frame)[tmp_frame.pc_offset];
+		frame = ((unsigned long *)frame)[tmp_frame.frame_offset];
+		if (frame < prev_sp || frame > stack_top) {
+		  printk("out of range sp %08lx,give up!\n",frame);
+		  break;
+		}
+
+	    retry_pc:
+		if (!__kernel_text_address(pc)) {
+		  printk("out of text addr %08lx,give up!\n",pc);
+		  break;
+		}
+
+		name = kallsyms_lookup(pc, &size, &offset, &modname, namebuf);
+		if (!name) {
+		  printk("no function found at %08lx\n",pc);
+		  return;
+		}
+		printk("%s at %08lx,frame=%08lx",name,pc,frame);
+
+		pc = pc - offset;
+		if (get_frame_info((void*)pc,&tmp_frame) && !in_exception) {
+		  printk("get frame information failed, assume exceptions\n");
+		  in_exception = 1;
+		  pc = regs->cp0_epc;
+		  frame = regs->regs[30];
+		  printk("epc = %08lx,frame=%08lx\n",pc,frame);
+		  goto retry_pc;
+		}
+	} while (count++ < 16);
+
+#if 0
 	const int field = 2 * sizeof(unsigned long);
 	unsigned long addr;

@@ -140,6 +261,7 @@
 		}
 	}
 	printk("\n");
+#endif
 }

 /*
@@ -147,9 +269,10 @@
  */
 void dump_stack(void)
 {
-	unsigned long stack;
+	//unsigned long stack;

-	show_trace(current, &stack);
+	//show_trace(current, &stack);
+	show_trace(current, NULL);
 }

 EXPORT_SYMBOL(dump_stack);
@@ -269,7 +392,8 @@
 	printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n",
 	        current->comm, current->pid, current_thread_info(), current);
 	show_stack(current, (long *) regs->regs[29]);
-	show_trace(current, (long *) regs->regs[29]);
+	//show_trace(current, (long *) regs->regs[29]);
+	show_trace(current,(void*) regs);
 	show_code((unsigned int *) regs->cp0_epc);
 	printk("\n");
 }



--- process.c.orig	2006-04-02 21:38:51.000000000 +0800
+++ process.c	2006-03-23 22:56:46.000000000 +0800
@@ -314,6 +314,9 @@
 	int i;
 	void *func = info->func;
 	union mips_instruction *ip = (union mips_instruction *)func;
+#ifdef CONFIG_FRAME_POINTER
+	info->omit_fp = 0;
+#endif
 	info->pc_offset = -1;
 	info->frame_offset = info->omit_fp ? 0 : -1;
 	for (i = 0; i < 128; i++, ip++) {

             reply	other threads:[~2006-04-02 14:27 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-04-02 14:38 Fuxin Zhang [this message]
2006-04-02 16:17 ` stack backtrace Atsushi Nemoto
2006-04-03  0:53   ` Fuxin Zhang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=442FE1CA.4030905@ict.ac.cn \
    --to=fxzhang@ict.ac.cn \
    --cc=linux-mips@linux-mips.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.