libunwind-devel
[Top][All Lists]
Advanced

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

[libunwind] libunwind 0.97 trouble on SuSE, works fine on RH


From: Johan Walles
Subject: [libunwind] libunwind 0.97 trouble on SuSE, works fine on RH
Date: Tue, 24 Aug 2004 13:22:50 +0200
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040113

Hi!

I'm running Libunwind on ia64.

The attached program is supposed to be a simple application of libunwind. It has a SIGSEGV signal handler that upon a crash prints the stack to stdout, marking the signal handler frame with '*'. On an RHAS21 system it says:

   0: 0x4000000000001850: crashhandler()
*  1: 0xa0000000000040d0: Unknown
   2: 0x4000000000001e00: crash()
   3: 0x4000000000001e50: callMeToo()
   4: 0x4000000000001eb0: callMe()
   5: 0x4000000000001f30: main()
   6: 0x200000000008c560: __libc_start_main()
   7: 0x40000000000014a0: _start()

This is what I expected. However, when I run the same program on either SuSE SLES 8.0 or 9.0, I get this instead:

   0: 0x4000000000001850: crashhandler()
*  1: 0xa0000000000040d0: Unknown
unw_step() failed: 3: Bad register number

Is this a problem with the example program or with something else (possibly libunwind)?

Since I'm not very much at home with the internal workings of libunwind, this is a bit tricky for me to debug. What I have managed to find out (assuming this really is a problem with libunwind) is that the UNW_EBADREG comes from:

#0 ia64_get (c=0x60000fffffff9860, loc=0x0, val=0x60000fffffff8da0) at ia64/unwind_i.h:206 #1 0x4000000000019510 in update_frame_state (c=0x60000fffffff9860) at ia64/Gstep-ia64.c:230 #2 0x4000000000019360 in _ULia64_step (cursor=0x60000fffffff9860) at ia64/Gstep-ia64.c:342
#3  0x4000000000001a10 in crashhandler (signo=0xb, siginfo=0x60000fffffffa8e0,
    contextAsVoid=0x60000fffffffa960) at libunwind.c:75
#4  <signal handler called>

The loc=0x0 passed to ia64_get() comes from ia64/Gstep-ia64.c:230:

 ret = ia64_get (c, c->loc[IA64_REG_IP], &ip);

The setting of c->loc[IA64_REG_IP] is done at:

#0 0x4000000000017da2 in run_script (script=0x6000000000029880, c=0x60000fffffff9860)
    at ia64/Gscript-ia64.c:628
#1 0x4000000000015cb0 in _ULia64_find_save_locs (c=0x60000fffffff9860) at ia64/Gscript-ia64.c:701 #2 0x40000000000192e0 in _ULia64_step (cursor=0x60000fffffff9860) at ia64/Gstep-ia64.c:338
#3  0x4000000000001a10 in crashhandler (signo=0xb, siginfo=0x60000fffffffa8e0,
    contextAsVoid=0x60000fffffffa960) at libunwind.c:75
#4  <signal handler called>

The local variables at that point are:

ip = (struct ia64_script_insn *) 0x6000000000029918
limit = (struct ia64_script_insn *) 0x6000000000029918
next_insn = {opc = 0x0, dst = 0x0, val = 0x0}
loc = 0x0
nat_loc = 0x0
opc = 0xb
dst = 0x7
nat_bitnr = 0x80
val = 0x200
ret = 0x0

So to sum this up, libunwind is running into problems on SuSE / ia64 systems, and I'd love to have this resolved. What would you think would be necessary to get to the bottom of this?

  Regards //Johan
/* 
 * The point of this program is simply to demonstrate libunwind
 * unwinding across an alternate signal handler frame.
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define UNW_LOCAL_ONLY
#include "libunwind.h"

static const char *
unw_strerror(int err)
{
   if (err < 0) {
      err = -err;
   }
   switch (err) {
   case UNW_ESUCCESS:       return "No error";
   case UNW_EUNSPEC:        return "Unspecified (general) error";
   case UNW_ENOMEM:         return "Out of memory";
   case UNW_EBADREG:        return "Bad register number";
   case UNW_EREADONLYREG:   return "Attempt to write read-only register";
   case UNW_ESTOPUNWIND:    return "Stop unwinding";
   case UNW_EINVALIDIP:     return "Invalid IP";
   case UNW_EBADFRAME:      return "Bad frame";
   case UNW_EINVAL:         return "Unsupported operation or bad value";
   case UNW_EBADVERSION:    return "Unwind info has unsupported version";
   case UNW_ENOINFO:        return "No unwind info found";
   default:                 return "Unknown error";
   }
}

void crashhandler(int signo, siginfo_t *siginfo, void *contextAsVoid)
{
   int result;
   int count = 0;
   ucontext_t context;
   unw_cursor_t cursor;
   
   // Fetch our current context
   result = unw_getcontext(&context);
   
   // Initialize unwinding
   if ((result = unw_init_local(&cursor, &context)) != 0) {
      fprintf(stderr, "unw_init_local: %s\n", unw_strerror(result));
      exit(EXIT_FAILURE);
   }
   
   // Print the stack trace
   do {
      char name[64];
      unw_word_t ip;
      unw_word_t off;
      
      // Print the stack frame
      result = unw_get_reg(&cursor, UNW_REG_IP, &ip);
      if (result < 0) {
         printf("unw_get_reg() failed: %d: %s\n", -result, 
unw_strerror(-result));
         exit(EXIT_FAILURE);
      }
      printf("%c%3d: %p: ",
             unw_is_signal_frame(&cursor) ? '*' : ' ',
             count,
             (void*)ip);
      if ((result = unw_get_proc_name(&cursor, name, sizeof(name), &off)) == 0) 
{
         printf("%s()", name);
      } else {
         printf("Unknown");
      }
      printf("\n");

      // Step
      result = unw_step(&cursor);
      count++;
   } while (result > 0);
   
   if (result < 0) {
      printf("unw_step() failed: %d: %s\n", -result, unw_strerror(-result));
   }
   
   exit(EXIT_SUCCESS);
}

void setUpCrashHandler()
{
   int result;
   struct sigaction action;
   
   action.sa_sigaction = crashhandler;
   sigfillset(&action.sa_mask);
   action.sa_flags = SA_SIGINFO;
   
   result = sigaction(SIGSEGV, &action, NULL);
   assert(result == 0);
}

void crash()
{
   volatile int i = *(int*)7;
   (void)i;
}

void callMeToo(void)
{
   crash();
}

void callMe(void)
{
   callMeToo();
}

int main(int argc, char *argv[])
{
   setUpCrashHandler();
   
   callMe();
   
   return 0;
}

reply via email to

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