libunwind-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [libunwind] problem unwinding signal handler on HPUX


From: Rob Faught
Subject: Re: [libunwind] problem unwinding signal handler on HPUX
Date: Mon, 10 Nov 2003 15:52:37 -0500
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.2.1) Gecko/20010901

David Mosberger wrote:

On Tue, 04 Nov 2003 19:06:02 -0500, Rob Faught <address@hidden> said:


  Rob> Hello David, It seems that the third argument to a signal
  Rob> handler is not a pointer to a full (48640 byte)
  Rob> ucontext_t. That is, sizeof(ucontext_t) is much larger than the
  Rob> data pushed on the stack. When ia64_uc_access_reg copies the
  Rob> ucontext its src pointer falls off the top of the stack with
  Rob> bad results. Instead grab the size field out of the ucontext_t
  Rob> and use that.

Something is fishy here.  ucontext_t is declared as:

typedef struct sigcontext mcontext_t;

typedef struct ucontext
  {
    union
      {
        mcontext_t _mc;
        struct
          {
            unsigned long _pad[_SC_GR0_OFFSET/8];
            struct ucontext *_link;     /* this should overlay sc_gr[0] */
          }
        _uc;
      }
    _u;
  }
ucontext_t;

so it is exactly as big as the "struct sigcontext" you get from the
kernel.  Can you provide a test-case that's failing for you?

        --david
_______________________________________________
libunwind mailing list
address@hidden
http://linux.hpl.hp.com/cgi-bin/mailman/listinfo/libunwind


I don't understand what is going on either. It just seems that the structure pushed on the stack is not as large as a ucontext_t. A mcontext_t is defined in include/machine/sys/newsig.h as:


typedef struct {
        __opaque128_t   __mc_opaque[2976];
} __mcontext_t;


The size of ucontext_t should be:
2976 * 16 + 1024(size of misc header + padding) = 48640 (0xbe00) bytes

The test below prints this as the sizeof(ucontext_t), but that is not the size of the data on the stack. Both the size field in the ucontext_t and the difference in the stack addresses agree that it is not.

-------------------------------------------------------------------------
#include <stdlib.h>
#include <signal.h>
#include <alloca.h>

/* compile
/opt/aCC/bin/aCC +DD64 -g  +noobjdebug testsig.cxx -o  testsig
*/

typedef void (*sigh)(int);
void *diff;

void handler(int s, int code, ucontext_t *sc)
{
  printf("handler %d code=%d sc=%p\n", s, code, sc);
printf("uc_size=%lx sizeof(ucontext_t)=%lx sizeof(sigcontext)=%lx diff=%lx\n", sc->__uc_misc.__uc_size, sizeof(ucontext_t), sizeof(struct sigcontext), (char *)diff-(char *)sc);

  return;
}

void recur(int r)
{
  if (r)
    recur(--r);
  else
    {
      diff = alloca(8);
      printf("before raise %p\n",diff);
      raise(2);
    }
}

int main(int argc, char *argv[])
{
  signal(SIGINT, (sigh)handler);
  recur(5);
  return 0;
}
---------------------------------------------------------------------

[hptarg:190] testsig
before raise 9ffffffffffff4d0
handler 2 code=0 sc=9fffffffffffa600
uc_size=4e00 sizeof(ucontext_t)=be00 sizeof(sigcontext)=be00 diff=4ed0

---------------------------------------------------------------------

The problem occurs when ia64_uc_access_reg tries to read the 0xbe00 bytes starting at 9fffffffffffa600. I get read errors around 0xa00000000000000.

My earlier suggestion for a fix is incomplete. I didn't change all the instances of sizeof(ucontext_t) in the file. It also doesn't allow me to backtrace over all my signal handler examples. One example has an unbound user thread for which I am not able to get a complete backtrace.

Rob




reply via email to

[Prev in Thread] Current Thread [Next in Thread]