public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Backtrace() called inside a signal handler traps while tracking an  invalid function call.
@ 2007-06-13 20:56 supriya kannery
  2007-06-13 21:05 ` Daniel Jacobowitz
  0 siblings, 1 reply; 2+ messages in thread
From: supriya kannery @ 2007-06-13 20:56 UTC (permalink / raw)
  To: gcc, libc-alpha; +Cc: suzuki

[-- Attachment #1: Type: text/plain, Size: 3096 bytes --]

Hello,
   Backtrace API is trapping when it is called inside a signal handler 
to trace back an invalid function call.

Backtrace API is called from a signal handler. When the SEGFAULT signal 
that is captured by the signal handler is due to the invokation of an 
invalid function call, then backtrace is generating SEGFAULT. In i586  
this segfault again gets captured by the signal handler, reaches 
backtrace, backtrace again generates segfault and infinite loop results. 
In x86_64 architecture, when backtrace generates segfault, the program 
stops.

Following code is an excerpt from gcc-3.3.3/gcc/unwind-dw2.c:
In x86_64 arch, fde is returned null for the invalid singal handler 
stack frame...
-------------------------------------------------------------------------------------------------------------------------- 

  fde = _Unwind_Find_FDE (context->ra - 1, &context->bases);
  if (fde == NULL)
    {
      /* Couldn't find frame unwind info for this function.  Try a
         target-specific fallback mechanism.  This will necessarily
         not provide a personality routine or LSDA.  */
#ifdef MD_FALLBACK_FRAME_STATE_FOR
    MD_FALLBACK_FRAME_STATE_FOR (context, fs, success);
      return _URC_END_OF_STACK;
-------------------------------------------------------------------------------------------------------------------------- 


MD_FALLBACK_FRAME_STATE_FOR macro is called which inturn checks the pc 
to see whether the backtrace is called from a signal hander
--------------------------------------------------------------------------------------------------------------------------
#ifdef __x86_64__
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS)               \
  do {                                                                  \
    unsigned char *pc_ = (CONTEXT)->ra;                                 \
    struct sigcontext *sc_;                                             \
    long new_cfa_;                                                      \
                                                                        \
    /* movq __NR_rt_sigreturn, %rax ; syscall  */                       \
    if (*(unsigned char *)(pc_+0) == 0x48                               \
        && *(unsigned long *)(pc_+1) == 0x050f0000000fc0c7)             \
      {                                                                 \
        struct ucontext *uc_ = (CONTEXT)->cfa;                          \
 --------------------------------------------------------------------------------------------------------------------------
SEGFAULT is generated while accessing the content of pc, as pc value is 
invalid (oxfffffe) for the invalid function call.

Is this scenario, of calling backtrace() on a stack containing invalid 
function pointer, a supported one? If yes, is there a way we can avoid 
accessing pc in this case and get onto unwind further stack frames ?
Btw, gdb is able to successfully unwind the full stack for this same 
scenario.

Attaching source files for recreating the problem: main.c and foo.c

Thanks, Supriya
IBM Linux Technology Centre


[-- Attachment #2: main.c --]
[-- Type: text/x-c, Size: 731 bytes --]

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

void foo( void ) ;

void catch_segv(int signum)
{
   int i, cnt ;
   void *syms[100] ;
   char buf[80] ;

   cnt = backtrace( syms, 100 ) ;

   for ( i = 0 ; i < cnt ; i++ )
   {
      snprintf( buf, sizeof(buf), "%d\t%lx\n", i, (unsigned long)syms[i] ) ;
      puts( buf ) ;
   }
}

int main( void )
{
   int rc ;
   struct sigaction newact;     /* Action */
   struct sigaction oldact;     /* Old action */

   newact.sa_handler = catch_segv;
   sigemptyset (&newact.sa_mask);
   newact.sa_flags = 0;

   rc = sigaction (SIGSEGV, &newact, &oldact);
   rc = sigaction (SIGBUS, &newact, &oldact);

   printf( "rc = %d, calling foo\n", rc ) ;

   foo() ;

  return 0 ;
}


[-- Attachment #3: foo.c --]
[-- Type: text/x-c, Size: 216 bytes --]

#include <stdio.h>

void (*fp)(void) = (void *)0xffffff ;

void foo( void )
{
  char buf[16] ;
  int cnt;
  
  buf[0] = '\n' ;
  buf[1] = '\0' ;

  printf( "Calling invalid function pointer.%s", buf ) ;

  fp() ;
}


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

* Re: Backtrace() called inside a signal handler traps while  tracking an  invalid function call.
  2007-06-13 20:56 Backtrace() called inside a signal handler traps while tracking an invalid function call supriya kannery
@ 2007-06-13 21:05 ` Daniel Jacobowitz
  0 siblings, 0 replies; 2+ messages in thread
From: Daniel Jacobowitz @ 2007-06-13 21:05 UTC (permalink / raw)
  To: supriya kannery; +Cc: gcc, libc-alpha, suzuki

On Thu, Jun 14, 2007 at 02:24:19AM +0530, supriya kannery wrote:
> Is this scenario, of calling backtrace() on a stack containing invalid function 
> pointer, a supported one?

In my opinion, no.  Attach a debugger instead.

-- 
Daniel Jacobowitz
CodeSourcery

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

end of thread, other threads:[~2007-06-13 21:05 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-06-13 20:56 Backtrace() called inside a signal handler traps while tracking an invalid function call supriya kannery
2007-06-13 21:05 ` Daniel Jacobowitz

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 read-only IMAP folder(s) and NNTP newsgroup(s).