diff -urp /usr/src/redhat/BUILD/ltrace-0.5/wait_for_something.c ltrace-0.5-64/wait_for_something.c --- /usr/src/redhat/BUILD/ltrace-0.5/wait_for_something.c 2011-10-25 17:35:00.000000000 -0400 +++ ltrace-0.5-64/wait_for_something.c 2011-10-25 16:17:31.000000000 -0400 @@ -165,6 +168,7 @@ struct event *wait_for_something(void) pid_t pid, child_pid; int status; int tmp; + int stop_signal; struct event * ev; if ((ev = next_qd_event()) != NULL) { @@ -292,16 +296,30 @@ struct event *wait_for_something(void) event.thing = LT_EV_UNKNOWN; return &event; } - if ((WSTOPSIG(status) != (SIGTRAP | event.proc->tracesysgood)) && - (WSTOPSIG(status) != SIGTRAP)) { + + stop_signal = WSTOPSIG(status); + event.thing = LT_EV_NONE; + + void * addr = event.proc->instruction_pointer - DECR_PC_AFTER_BREAK; + + /* On some targets (ia64, s390x), breakpoints are signalled + not using SIGTRAP, but also with SIGILL, SIGSEGV or SIGEMT. + Check for these. */ + if (stop_signal == SIGSEGV || stop_signal == SIGILL) { + if (address2bpstruct(leader, addr)) + stop_signal = SIGTRAP; + } + + if (event.thing == LT_EV_NONE + && (stop_signal != (SIGTRAP | event.proc->tracesysgood)) + && (stop_signal != SIGTRAP)) { event.thing = LT_EV_SIGNAL; - event.e_un.signum = WSTOPSIG(status); + event.e_un.signum = stop_signal; return &event; } event.thing = LT_EV_BREAKPOINT; - event.e_un.brk_addr = - event.proc->instruction_pointer - DECR_PC_AFTER_BREAK; + event.e_un.brk_addr = addr; return &event; }