linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* Signal backtrace function
@ 2008-04-09 18:16 Joakim Tjernlund
  2008-04-14 16:09 ` Detlev Zundel
  0 siblings, 1 reply; 4+ messages in thread
From: Joakim Tjernlund @ 2008-04-09 18:16 UTC (permalink / raw)
  To: 'linuxppc-dev Development'

Hi

I made my own backtrace function for printing
a trace from within a signal handler. Maybe it
can be useful for the kernel too? General
comments welcome.


   Jocke

#include <stdio.h>
#include <signal.h>
#include <execinfo.h>
#include <unistd.h>

#define __USE_GNU
#include <ucontext.h>

/* This is the stack layout we see with every stack frame.
   Note that every routine is required by the ABI to lay out the stack
   like this.

            +----------------+        +-----------------+
    %r1  -> | %r1 last frame--------> | %r1 last frame--->...  --> NULL
            |                |        |                 |
            | (unused)       |        | return address  |
            +----------------+        +-----------------+
*/


/* Prints a backtrace when invoked from a signal handler */
int
sigbacktrace (void **array, int size, void *sp,
	     void *lr, void *exec_addr)
{
	int count=1, loop;
	void *ret_addr;
	struct layout {
		struct layout * next;
		void * return_address;
	} *current;
	
	if (!size)
		return size;
	current = sp;
	array[0] = exec_addr;

	for (loop = 0;
	     current != NULL && count < size;
	     current = current->next, loop++) {
		ret_addr = current->return_address;
#if DEBUG
		printf("next:%p, ret:%p, LR:%p\n", current->next, ret_addr, lr);
#endif
		if (lr == ret_addr) /* false frame ? */
			continue;
		if (!loop)
			if (lr != ret_addr) /*  Leaf function ? */
				ret_addr = lr;
			else
				continue;
		array[count++] = ret_addr;
	}

	/* It's possible the second-last stack frame can't return in which
	   case the CRT startup code will have set its LR to 'NULL'.  */
	if (count > 0 && array[count-1] == NULL)
		count--;

	return count;
}

#define EXEC_ADDR (*regs)[32]
#define STK_PTR (*regs)[1]
#define LINK (*regs)[36]
void bt_sighandler(int sig, siginfo_t *info,
		   void *secret)
{

  void *trace[16];
  char **messages = (char **)NULL;
  int i, trace_size = 0;
  ucontext_t *uc = (ucontext_t *)secret;
  gregset_t *regs = &uc->uc_mcontext.uc_regs->gregs;

  /* Do something useful with siginfo_t */
  if (sig == SIGSEGV || sig == SIGBUS)
	printf("Got signal %d, faulty address is %p, "
		   "from %p\n", sig, info->si_addr,
	       EXEC_ADDR);
  else
	printf("Got signal %d\n", sig);
  trace_size = sigbacktrace(trace, 16, (void*) STK_PTR,
			    (void*) LINK, (void*) EXEC_ADDR);
  messages = backtrace_symbols(trace, trace_size);
  printf("[bt] Execution path:\n");
  for (i=0; i<trace_size; ++i)
	printf("[bt] %s\n", messages[i]);

  if (sig != SIGUSR1)
	  exit(0);
}

void dummy(void)
{
  unsigned long *current;
  asm volatile ("" : "=l"(current));
}

int func_a(int a, char b) {

  char *p = (char *)0xdeadbeef;
  //dummy(); /* Test with and without this call */
  a = a + b;
  *p = 10;	/* CRASH here!! */
  dummy(); /* Test with and without this call */

  return 2*a;
}


int func_b() {
  
  int res, a = 5;

  res = 5 + func_a(a, 't');

  return res;
}


int main() {

  /* Install our signal handler */
  struct sigaction sa;

  sa.sa_sigaction = (void *)bt_sighandler;
  sigemptyset (&sa.sa_mask);
  sa.sa_flags = SA_RESTART | SA_SIGINFO;

  sigaction(SIGSEGV, &sa, NULL);
  sigaction(SIGBUS, &sa, NULL);
  sigaction(SIGUSR1, &sa, NULL);
  /* ... add any other signal here */

  /* Do something */
  printf("%d\n", func_b());

}

 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Signal backtrace function
  2008-04-09 18:16 Signal backtrace function Joakim Tjernlund
@ 2008-04-14 16:09 ` Detlev Zundel
  2008-04-14 16:20   ` Joakim Tjernlund
  0 siblings, 1 reply; 4+ messages in thread
From: Detlev Zundel @ 2008-04-14 16:09 UTC (permalink / raw)
  To: linuxppc-dev

Hi Jocke,

> I made my own backtrace function for printing
> a trace from within a signal handler. Maybe it
> can be useful for the kernel too? General
> comments welcome.

Probably a dumb question, but doesn't backtrace(3) from glibc work
architecture independent already?   Why do you need to reimplement it?

Thanks
  Detlev

-- 
The management question  ...  is not  _whether_  to build a pilot system
and throw it away.  You _will_ do that.  The only question is whether to
plan  in advance  to build  a throwaway,  or  to promise  to deliver the
throwaway to customers.          - Fred Brooks, "The Mythical Man Month"
--
DENX Software Engineering GmbH,      MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich,  Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-40 Fax: (+49)-8142-66989-80 Email: dzu@denx.de

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Signal backtrace function
  2008-04-14 16:09 ` Detlev Zundel
@ 2008-04-14 16:20   ` Joakim Tjernlund
  2008-04-15 15:50     ` Detlev Zundel
  0 siblings, 1 reply; 4+ messages in thread
From: Joakim Tjernlund @ 2008-04-14 16:20 UTC (permalink / raw)
  To: Detlev Zundel; +Cc: linuxppc-dev


On Mon, 2008-04-14 at 18:09 +0200, Detlev Zundel wrote:
> Hi Jocke,
> 
> > I made my own backtrace function for printing
> > a trace from within a signal handler. Maybe it
> > can be useful for the kernel too? General
> > comments welcome.
> 
> Probably a dumb question, but doesn't backtrace(3) from glibc work
> architecture independent already?   Why do you need to reimplement it?

Nope, it doesn't give you a good backtrace from within a signal handler.
On x86 you can use the normal backtrace function with a minor
workaround, but as ppc doesn't save a FP in leaf functions, that
workaround does not work well. You can read more about it
at http://www.linuxjournal.com/article/6391

 Jocke

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Signal backtrace function
  2008-04-14 16:20   ` Joakim Tjernlund
@ 2008-04-15 15:50     ` Detlev Zundel
  0 siblings, 0 replies; 4+ messages in thread
From: Detlev Zundel @ 2008-04-15 15:50 UTC (permalink / raw)
  To: joakim.tjernlund; +Cc: linuxppc-dev

Hi Jocke,

> On Mon, 2008-04-14 at 18:09 +0200, Detlev Zundel wrote:
>> Hi Jocke,
>> 
>> > I made my own backtrace function for printing
>> > a trace from within a signal handler. Maybe it
>> > can be useful for the kernel too? General
>> > comments welcome.
>> 
>> Probably a dumb question, but doesn't backtrace(3) from glibc work
>> architecture independent already?   Why do you need to reimplement it?
>
> Nope, it doesn't give you a good backtrace from within a signal handler.
> On x86 you can use the normal backtrace function with a minor
> workaround, but as ppc doesn't save a FP in leaf functions, that
> workaround does not work well. You can read more about it
> at http://www.linuxjournal.com/article/6391

Thanks for clearing that up.  I wasn't aware of that limitation.

Cheers
  Detlev

-- 
In short: much of our country's [USA] counterterrorism security spending is
not designed to protect us from the terrorists,  but instead to protect our
public officials from criticism when another attack occurs.
                                   -- Bruce Schneier
--
DENX Software Engineering GmbH,      MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich,  Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-40 Fax: (+49)-8142-66989-80 Email: dzu@denx.de

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2008-04-15 15:51 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-04-09 18:16 Signal backtrace function Joakim Tjernlund
2008-04-14 16:09 ` Detlev Zundel
2008-04-14 16:20   ` Joakim Tjernlund
2008-04-15 15:50     ` Detlev Zundel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).