[Top][All Lists]
[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;
}
- [libunwind] libunwind 0.97 trouble on SuSE, works fine on RH,
Johan Walles <=