Support vfork and fix a bunch of errors
This commit is contained in:
parent
7e4d565871
commit
d2c71fc092
30
ltrace-0.6.0-ppc-args.patch
Normal file
30
ltrace-0.6.0-ppc-args.patch
Normal file
@ -0,0 +1,30 @@
|
||||
diff --git a/sysdeps/linux-gnu/ppc/trace.c b/sysdeps/linux-gnu/ppc/trace.c
|
||||
index 20b3f5d..321e6ec 100644
|
||||
--- a/sysdeps/linux-gnu/ppc/trace.c
|
||||
+++ b/sysdeps/linux-gnu/ppc/trace.c
|
||||
@@ -87,10 +87,22 @@ gimme_arg_regset(enum tof type, Process *proc, int arg_num, arg_type_info *info,
|
||||
}
|
||||
else if (greg <= 10)
|
||||
return (*regs)[greg++];
|
||||
- else
|
||||
+ else {
|
||||
+#ifdef __powerpc64__
|
||||
+ if (proc->mask_32bit)
|
||||
+ return ptrace (PTRACE_PEEKDATA, proc->pid,
|
||||
+ proc->stack_pointer + 8 +
|
||||
+ sizeof (int) * (arg_num - 8), 0) >> 32;
|
||||
+ else
|
||||
+ return ptrace (PTRACE_PEEKDATA, proc->pid,
|
||||
+ proc->stack_pointer + 112 +
|
||||
+ sizeof (long) * (arg_num - 8), 0);
|
||||
+#else
|
||||
return ptrace (PTRACE_PEEKDATA, proc->pid,
|
||||
- proc->stack_pointer + sizeof (long) *
|
||||
- (arg_num - 8), 0);
|
||||
+ proc->stack_pointer + 8 +
|
||||
+ sizeof (long) * (arg_num - 8), 0);
|
||||
+#endif
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
}
|
||||
21
ltrace-0.6.0-ppc-shift.patch
Normal file
21
ltrace-0.6.0-ppc-shift.patch
Normal file
@ -0,0 +1,21 @@
|
||||
diff --git a/sysdeps/linux-gnu/ppc/plt.c b/sysdeps/linux-gnu/ppc/plt.c
|
||||
index 980d028..668f63d 100644
|
||||
--- a/sysdeps/linux-gnu/ppc/plt.c
|
||||
+++ b/sysdeps/linux-gnu/ppc/plt.c
|
||||
@@ -44,12 +44,16 @@ sym2addr(Process *proc, struct library_symbol *sym) {
|
||||
|
||||
pt_ret = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0);
|
||||
|
||||
+#if SIZEOF_LONG == 8
|
||||
if (proc->mask_32bit) {
|
||||
// Assume big-endian.
|
||||
addr = (void *)((pt_ret >> 32) & 0xffffffff);
|
||||
} else {
|
||||
addr = (void *)pt_ret;
|
||||
}
|
||||
+#else
|
||||
+ addr = (void *)pt_ret;
|
||||
+#endif
|
||||
|
||||
return addr;
|
||||
}
|
||||
406
ltrace-0.6.0-thread-races.patch
Normal file
406
ltrace-0.6.0-thread-races.patch
Normal file
@ -0,0 +1,406 @@
|
||||
diff --git a/common.h b/common.h
|
||||
index 2fff8dd..715898d 100644
|
||||
--- a/common.h
|
||||
+++ b/common.h
|
||||
@@ -343,6 +343,7 @@ extern void disable_breakpoint(Process * proc, Breakpoint * sbp);
|
||||
extern int syscall_p(Process * proc, int status, int * sysnum);
|
||||
extern void continue_process(pid_t pid);
|
||||
extern void continue_after_signal(pid_t pid, int signum);
|
||||
+extern void continue_after_syscall(Process *proc, int sysnum, int ret_p);
|
||||
extern void continue_after_breakpoint(Process * proc, Breakpoint * sbp);
|
||||
extern void continue_after_vfork(Process * proc);
|
||||
extern void ltrace_exiting(void);
|
||||
diff --git a/handle_event.c b/handle_event.c
|
||||
index f56c537..203459c 100644
|
||||
--- a/handle_event.c
|
||||
+++ b/handle_event.c
|
||||
@@ -70,7 +70,9 @@ handle_event(Event *event) {
|
||||
|
||||
/* Note: the previous handler has a chance to alter
|
||||
* the event. */
|
||||
- if (event->proc->leader != NULL) {
|
||||
+ if (event->proc != NULL
|
||||
+ && event->proc->leader != NULL
|
||||
+ && event->proc != event->proc->leader) {
|
||||
event = call_handler(event->proc->leader, event);
|
||||
if (event == NULL)
|
||||
return;
|
||||
@@ -454,7 +456,7 @@ handle_syscall(Event *event) {
|
||||
enable_all_breakpoints(event->proc);
|
||||
}
|
||||
}
|
||||
- continue_process(event->proc->pid);
|
||||
+ continue_after_syscall(event->proc, event->e_un.sysnum, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -533,9 +535,12 @@ handle_sysret(Event *event) {
|
||||
output_right(LT_TOF_SYSCALLR, event->proc,
|
||||
sysname(event->proc, event->e_un.sysnum));
|
||||
}
|
||||
+ assert(event->proc->callstack_depth > 0);
|
||||
+ unsigned d = event->proc->callstack_depth - 1;
|
||||
+ assert(event->proc->callstack[d].is_syscall);
|
||||
callstack_pop(event->proc);
|
||||
}
|
||||
- continue_process(event->proc->pid);
|
||||
+ continue_after_syscall(event->proc, event->e_un.sysnum, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -639,7 +644,7 @@ handle_breakpoint(Event *event) {
|
||||
struct library_symbol *sym= event->proc->callstack[i].c_un.libfunc;
|
||||
struct library_symbol *new_sym;
|
||||
assert(sym);
|
||||
- addr = sym2addr(leader, sym);
|
||||
+ addr = sym2addr(event->proc, sym);
|
||||
sbp = dict_find_entry(leader->breakpoints, addr);
|
||||
if (sbp) {
|
||||
if (addr != sbp->addr) {
|
||||
diff --git a/sysdeps/linux-gnu/events.c b/sysdeps/linux-gnu/events.c
|
||||
index 0685342..021192f 100644
|
||||
--- a/sysdeps/linux-gnu/events.c
|
||||
+++ b/sysdeps/linux-gnu/events.c
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <string.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <assert.h>
|
||||
+#include <unistd.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -138,6 +139,26 @@ next_event(void)
|
||||
}
|
||||
event.proc = pid2proc(pid);
|
||||
if (!event.proc || event.proc->state == STATE_BEING_CREATED) {
|
||||
+ /* Work around (presumably) a bug on some kernels,
|
||||
+ * where we are seeing a waitpid event even though the
|
||||
+ * process is still reported to be running. Wait for
|
||||
+ * the tracing stop to propagate. But don't get stuck
|
||||
+ * here forever.
|
||||
+ *
|
||||
+ * We need the process in T, because there's a lot of
|
||||
+ * ptracing going on all over the place, and these
|
||||
+ * calls fail when the process is not in T.
|
||||
+ *
|
||||
+ * N.B. This was observed on RHEL 5 Itanium, but I'm
|
||||
+ * turning this on globally, to save some poor soul
|
||||
+ * down the road (which could well be me a year from
|
||||
+ * now) the pain of figuring this out all over again.
|
||||
+ * Petr Machata 2011-11-22. */
|
||||
+ int i = 0;
|
||||
+ for (; i < 100 && process_status(pid) != ps_tracing_stop; ++i) {
|
||||
+ debug(2, "waiting for %d to stop", pid);
|
||||
+ usleep(10000);
|
||||
+ }
|
||||
event.type = EVENT_NEW;
|
||||
event.e_un.newpid = pid;
|
||||
debug(DEBUG_EVENT, "event: NEW: pid=%d", pid);
|
||||
diff --git a/sysdeps/linux-gnu/ia64/regs.c b/sysdeps/linux-gnu/ia64/regs.c
|
||||
index 00df572..3f5d951 100644
|
||||
--- a/sysdeps/linux-gnu/ia64/regs.c
|
||||
+++ b/sysdeps/linux-gnu/ia64/regs.c
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ptrace.h>
|
||||
+#include <errno.h>
|
||||
|
||||
#include <asm/ptrace_offsets.h>
|
||||
#include <asm/rse.h>
|
||||
@@ -36,12 +37,18 @@ set_instruction_pointer(Process *proc, void *addr) {
|
||||
|
||||
void *
|
||||
get_stack_pointer(Process *proc) {
|
||||
- return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, PT_R12, 0);
|
||||
+ long l = ptrace(PTRACE_PEEKUSER, proc->pid, PT_R12, 0);
|
||||
+ if (l == -1 && errno)
|
||||
+ return NULL;
|
||||
+ return (void *)l;
|
||||
}
|
||||
|
||||
void *
|
||||
get_return_addr(Process *proc, void *stack_pointer) {
|
||||
- return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, PT_B0, 0);
|
||||
+ long l = ptrace(PTRACE_PEEKUSER, proc->pid, PT_B0, 0);
|
||||
+ if (l == -1 && errno)
|
||||
+ return NULL;
|
||||
+ return (void *)l;
|
||||
}
|
||||
|
||||
void
|
||||
diff --git a/sysdeps/linux-gnu/ia64/trace.c b/sysdeps/linux-gnu/ia64/trace.c
|
||||
index 799e0ff..079ed55 100644
|
||||
--- a/sysdeps/linux-gnu/ia64/trace.c
|
||||
+++ b/sysdeps/linux-gnu/ia64/trace.c
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <string.h>
|
||||
#include <asm/ptrace_offsets.h>
|
||||
#include <asm/rse.h>
|
||||
+#include <errno.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -48,9 +49,10 @@ int
|
||||
syscall_p(Process *proc, int status, int *sysnum) {
|
||||
if (WIFSTOPPED(status)
|
||||
&& WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
|
||||
- unsigned long slot =
|
||||
- (ptrace(PTRACE_PEEKUSER, proc->pid, PT_CR_IPSR, 0) >> 41) &
|
||||
- 0x3;
|
||||
+ long l = ptrace(PTRACE_PEEKUSER, proc->pid, PT_CR_IPSR, 0);
|
||||
+ if (l == -1 && errno)
|
||||
+ return -1;
|
||||
+ unsigned long slot = ((unsigned long)l >> 41) & 0x3;
|
||||
unsigned long ip =
|
||||
ptrace(PTRACE_PEEKUSER, proc->pid, PT_CR_IIP, 0);
|
||||
|
||||
diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c
|
||||
index ba3806d..db18df0 100644
|
||||
--- a/sysdeps/linux-gnu/trace.c
|
||||
+++ b/sysdeps/linux-gnu/trace.c
|
||||
@@ -146,8 +146,8 @@ continue_process(pid_t pid)
|
||||
debug(DEBUG_PROCESS, "continue_process: pid=%d", pid);
|
||||
|
||||
/* Only really continue the process if there are no events in
|
||||
- the queue for this process. Otherwise just for the other
|
||||
- events to arrive. */
|
||||
+ the queue for this process. Otherwise just wait for the
|
||||
+ other events to arrive. */
|
||||
if (!have_events_for(pid))
|
||||
/* We always trace syscalls to control fork(),
|
||||
* clone(), execve()... */
|
||||
@@ -168,6 +168,7 @@ struct pid_task {
|
||||
int got_event : 1;
|
||||
int delivered : 1;
|
||||
int vforked : 1;
|
||||
+ int sysret : 1;
|
||||
} * pids;
|
||||
|
||||
struct pid_set {
|
||||
@@ -259,10 +260,14 @@ task_stopped(Process * task, void * data)
|
||||
case ps_invalid:
|
||||
case ps_tracing_stop:
|
||||
case ps_zombie:
|
||||
+ case ps_sleeping:
|
||||
return pcb_cont;
|
||||
- default:
|
||||
+ case ps_stop:
|
||||
+ case ps_other:
|
||||
return pcb_stop;
|
||||
}
|
||||
+
|
||||
+ abort ();
|
||||
}
|
||||
|
||||
/* Task is blocked if it's stopped, or if it's a vfork parent. */
|
||||
@@ -376,7 +381,8 @@ process_stopping_done(struct process_stopping_handler * self, Process * leader)
|
||||
if (!self->exiting) {
|
||||
for (i = 0; i < self->pids.count; ++i)
|
||||
if (self->pids.tasks[i].pid != 0
|
||||
- && self->pids.tasks[i].delivered)
|
||||
+ && (self->pids.tasks[i].delivered
|
||||
+ || self->pids.tasks[i].sysret))
|
||||
continue_process(self->pids.tasks[i].pid);
|
||||
continue_process(self->task_enabling_breakpoint->pid);
|
||||
destroy_event_handler(leader);
|
||||
@@ -469,7 +475,10 @@ handle_stopping_event(struct pid_task * task_info, Event ** eventp)
|
||||
/* Some SIGSTOPs may have not been delivered to their respective tasks
|
||||
* yet. They are still in the queue. If we have seen an event for
|
||||
* that process, continue it, so that the SIGSTOP can be delivered and
|
||||
- * caught by ltrace. */
|
||||
+ * caught by ltrace. We don't mind that the process is after
|
||||
+ * breakpoint (and therefore potentially doesn't have aligned IP),
|
||||
+ * because the signal will be delivered without the process actually
|
||||
+ * starting. */
|
||||
static void
|
||||
continue_for_sigstop_delivery(struct pid_set * pids)
|
||||
{
|
||||
@@ -549,6 +558,14 @@ all_stops_accountable(struct pid_set * pids)
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static void
|
||||
+singlestep(Process * proc)
|
||||
+{
|
||||
+ debug(1, "PTRACE_SINGLESTEP");
|
||||
+ if (ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0))
|
||||
+ perror("PTRACE_SINGLESTEP");
|
||||
+}
|
||||
+
|
||||
/* This event handler is installed when we are in the process of
|
||||
* stopping the whole thread group to do the pointer re-enablement for
|
||||
* one of the threads. We pump all events to the queue for later
|
||||
@@ -580,6 +597,17 @@ process_stopping_on_event(Event_Handler * super, Event * event)
|
||||
if (event_exit_p(event) && task_info != NULL)
|
||||
task_info->pid = 0;
|
||||
|
||||
+ /* Always handle sysrets. Whether sysret occurred and what
|
||||
+ * sys it rets from may need to be determined based on process
|
||||
+ * stack, so we need to keep that in sync with reality. Note
|
||||
+ * that we don't continue the process after the sysret is
|
||||
+ * handled. See continue_after_syscall. */
|
||||
+ if (event != NULL && event->type == EVENT_SYSRET) {
|
||||
+ debug(1, "%d LT_EV_SYSRET", event->proc->pid);
|
||||
+ event_to_queue = 0;
|
||||
+ task_info->sysret = 1;
|
||||
+ }
|
||||
+
|
||||
switch (state) {
|
||||
case psh_stopping:
|
||||
/* If everyone is stopped, singlestep. */
|
||||
@@ -588,16 +616,22 @@ process_stopping_on_event(Event_Handler * super, Event * event)
|
||||
teb->pid);
|
||||
if (sbp->enabled)
|
||||
disable_breakpoint(teb, sbp);
|
||||
- if (ptrace(PTRACE_SINGLESTEP, teb->pid, 0, 0))
|
||||
- perror("PTRACE_SINGLESTEP");
|
||||
+ singlestep(teb);
|
||||
self->state = state = psh_singlestep;
|
||||
}
|
||||
break;
|
||||
|
||||
- case psh_singlestep: {
|
||||
+ case psh_singlestep:
|
||||
/* In singlestep state, breakpoint signifies that we
|
||||
* have now stepped, and can re-enable the breakpoint. */
|
||||
if (event != NULL && task == teb) {
|
||||
+
|
||||
+ /* This is not the singlestep that we are waiting for. */
|
||||
+ if (event->type == EVENT_SIGNAL) {
|
||||
+ singlestep(task);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
/* Essentially we don't care what event caused
|
||||
* the thread to stop. We can do the
|
||||
* re-enablement now. */
|
||||
@@ -613,7 +647,6 @@ process_stopping_on_event(Event_Handler * super, Event * event)
|
||||
event = NULL; // handled
|
||||
} else
|
||||
break;
|
||||
- }
|
||||
|
||||
/* fall-through */
|
||||
|
||||
@@ -806,9 +839,6 @@ ltrace_exiting_install_handler(Process * proc)
|
||||
* with its parent, and handle it as a multi-threaded case, with the
|
||||
* exception that we know that the parent is blocked, and don't
|
||||
* attempt to stop it. When the child execs, we undo the setup.
|
||||
- *
|
||||
- * XXX The parent process could be un-suspended before ltrace gets
|
||||
- * child exec/exit event. Make sure this is taken care of.
|
||||
*/
|
||||
|
||||
struct process_vfork_handler
|
||||
@@ -840,9 +870,9 @@ process_vfork_on_event(Event_Handler * super, Event * event)
|
||||
sbp = dict_find_entry(event->proc->leader->breakpoints,
|
||||
self->bp_addr);
|
||||
if (sbp != NULL)
|
||||
- insert_breakpoint(event->proc->leader,
|
||||
- self->bp_addr, sbp->libsym,
|
||||
- 1);
|
||||
+ insert_breakpoint(event->proc->parent,
|
||||
+ self->bp_addr,
|
||||
+ sbp->libsym, 1);
|
||||
}
|
||||
|
||||
continue_process(event->proc->parent->pid);
|
||||
@@ -852,11 +882,6 @@ process_vfork_on_event(Event_Handler * super, Event * event)
|
||||
change_process_leader(event->proc, event->proc);
|
||||
destroy_event_handler(event->proc);
|
||||
|
||||
- /* XXXXX this could happen in the middle of handling
|
||||
- * multi-threaded breakpoint. We must be careful to
|
||||
- * undo the effects that we introduced above (vforked
|
||||
- * = 1 et.al.). */
|
||||
-
|
||||
default:
|
||||
;
|
||||
}
|
||||
@@ -893,6 +918,27 @@ continue_after_vfork(Process * proc)
|
||||
change_process_leader(proc, proc->parent->leader);
|
||||
}
|
||||
|
||||
+static int
|
||||
+is_mid_stopping(Process *proc)
|
||||
+{
|
||||
+ return proc != NULL
|
||||
+ && proc->event_handler != NULL
|
||||
+ && proc->event_handler->on_event == &process_stopping_on_event;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+continue_after_syscall(Process * proc, int sysnum, int ret_p)
|
||||
+{
|
||||
+ /* Don't continue if we are mid-stopping. */
|
||||
+ if (ret_p && (is_mid_stopping(proc) || is_mid_stopping(proc->leader))) {
|
||||
+ debug(DEBUG_PROCESS,
|
||||
+ "continue_after_syscall: don't continue %d",
|
||||
+ proc->pid);
|
||||
+ return;
|
||||
+ }
|
||||
+ continue_process(proc->pid);
|
||||
+}
|
||||
+
|
||||
/* If ltrace gets SIGINT, the processes directly or indirectly run by
|
||||
* ltrace get it too. We just have to wait long enough for the signal
|
||||
* to be delivered and the process terminated, which we notice and
|
||||
diff --git a/testsuite/ltrace.main/hello-vfork.c b/testsuite/ltrace.main/hello-vfork.c
|
||||
new file mode 100644
|
||||
index 0000000..228c052
|
||||
--- /dev/null
|
||||
+++ b/testsuite/ltrace.main/hello-vfork.c
|
||||
@@ -0,0 +1,11 @@
|
||||
+/* Copyright (C) 2008, Red Hat, Inc.
|
||||
+ * Written by Denys Vlasenko */
|
||||
+#include <stdio.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+int main() {
|
||||
+ int r = vfork();
|
||||
+ fprintf(stderr, "vfork():%d\n", r);
|
||||
+ _exit(0);
|
||||
+}
|
||||
+
|
||||
diff --git a/testsuite/ltrace.main/hello-vfork.exp b/testsuite/ltrace.main/hello-vfork.exp
|
||||
new file mode 100644
|
||||
index 0000000..12c9ca3
|
||||
--- /dev/null
|
||||
+++ b/testsuite/ltrace.main/hello-vfork.exp
|
||||
@@ -0,0 +1,35 @@
|
||||
+# This file was written by Yao Qi <qiyao@cn.ibm.com>.
|
||||
+
|
||||
+set testfile "hello-vfork"
|
||||
+set srcfile ${testfile}.c
|
||||
+set binfile ${testfile}
|
||||
+
|
||||
+
|
||||
+if [get_compiler_info $binfile] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+verbose "compiling source file now....."
|
||||
+if { [ltrace_compile $srcdir/$subdir/$srcfile $objdir/$subdir/$binfile executable debug ] != ""} {
|
||||
+ send_user "Testcase compile failed, so all tests in this file will automatically fail.\n"
|
||||
+}
|
||||
+
|
||||
+# set options for ltrace.
|
||||
+ltrace_options "-f"
|
||||
+
|
||||
+# Run PUT for ltarce.
|
||||
+set exec_output [ltrace_runtest $objdir/$subdir $objdir/$subdir/$binfile]
|
||||
+
|
||||
+# Check the output of this program.
|
||||
+verbose "ltrace runtest output: $exec_output\n"
|
||||
+if [regexp {ELF from incompatible architecture} $exec_output] {
|
||||
+ fail "32-bit ltrace can not perform on 64-bit PUTs and rebuild ltrace in 64 bit mode!"
|
||||
+ return
|
||||
+} elseif [ regexp {Couldn't get .hash data} $exec_output ] {
|
||||
+ fail "Couldn't get .hash data!"
|
||||
+ return
|
||||
+}
|
||||
+
|
||||
+# Verify the output by checking numbers of print in main-vfork.ltrace.
|
||||
+ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace "_exit" 2
|
||||
+ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace "vfork resumed" 2
|
||||
1130
ltrace-0.6.0-vfork.patch
Normal file
1130
ltrace-0.6.0-vfork.patch
Normal file
File diff suppressed because it is too large
Load Diff
16
ltrace.spec
16
ltrace.spec
@ -23,6 +23,10 @@ Patch5: ltrace-0.6.0-return-string-n.patch
|
||||
Patch6: ltrace-0.6.0-threads.patch
|
||||
Patch7: ltrace-0.6.0-endian.patch
|
||||
Patch8: ltrace-0.6.0-clone-test.patch
|
||||
Patch9: ltrace-0.6.0-ppc-args.patch
|
||||
Patch10: ltrace-0.6.0-ppc-shift.patch
|
||||
Patch11: ltrace-0.6.0-vfork.patch
|
||||
Patch12: ltrace-0.6.0-thread-races.patch
|
||||
|
||||
%description
|
||||
Ltrace is a debugging program which runs a specified command until the
|
||||
@ -44,6 +48,10 @@ execution of processes.
|
||||
%patch6 -p1
|
||||
%patch7 -p1
|
||||
%patch8 -p1
|
||||
%patch9 -p1
|
||||
%patch10 -p1
|
||||
%patch11 -p1
|
||||
%patch12 -p1
|
||||
sed -i -e 's/-o root -g root//' Makefile.in
|
||||
|
||||
%build
|
||||
@ -76,6 +84,14 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%config(noreplace) %{_sysconfdir}/ltrace.conf
|
||||
|
||||
%changelog
|
||||
* Fri Nov 25 2011 Petr Machata <pmachata@redhat.com> - 0.6.0-4
|
||||
- Add several upstream patches that fix various races in tracing
|
||||
multi-threaded processes
|
||||
- Add upstream patches for support of tracing across vfork
|
||||
- Add upstream patches for ppc: excessive shift, and fetching
|
||||
function arguments
|
||||
- Bump up revision to preserve upgrade path
|
||||
|
||||
* Fri Sep 2 2011 Petr Machata <pmachata@redhat.com> - 0.6.0-2
|
||||
- Add upstream patches for tracing multi-threaded processes, endian
|
||||
fixes, and a test suite fixlet
|
||||
|
||||
Loading…
Reference in New Issue
Block a user