Upstream 0.7.0
This commit is contained in:
parent
f09484d326
commit
85e550411c
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
ltrace-0.5-svn45.tar.gz
|
||||
ltrace-*/
|
||||
/ltrace-0.6.0.tar.bz2
|
||||
/ltrace-0.7.0.tar.bz2
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
diff -up ltrace-0.5/etc/ltrace.conf\~ ltrace-0.5/etc/ltrace.conf
|
||||
--- ltrace-0.5/etc/ltrace.conf~ 2006-02-20 22:55:47.000000000 +0100
|
||||
+++ ltrace-0.5/etc/ltrace.conf 2010-12-09 12:24:31.000000000 +0100
|
||||
@@ -237,6 +237,7 @@ string basename(string);
|
||||
string index(string,char);
|
||||
addr memchr(string,char,ulong);
|
||||
addr memcpy(addr,string3,ulong);
|
||||
+addr memmove(addr,string3,ulong);
|
||||
addr memset(addr,char,long);
|
||||
string rindex(string,char);
|
||||
addr stpcpy(addr,string);
|
||||
|
||||
Diff finished. Thu Dec 9 12:24:37 2010
|
||||
@ -1,84 +0,0 @@
|
||||
diff -Nurp ltrace-0.5-orig/testsuite/ltrace.torture/ia64-sigill.exp ltrace-0.5/testsuite/ltrace.torture/ia64-sigill.exp
|
||||
--- ltrace-0.5-orig/testsuite/ltrace.torture/ia64-sigill.exp 1969-12-31 19:00:00.000000000 -0500
|
||||
+++ ltrace-0.5/testsuite/ltrace.torture/ia64-sigill.exp 2007-05-04 13:29:43.000000000 -0400
|
||||
@@ -0,0 +1,33 @@
|
||||
+# This file was written by Yao Qi <qiyao@cn.ibm.com>.
|
||||
+
|
||||
+set testfile "ia64-sigill"
|
||||
+set srcfile ${testfile}.s
|
||||
+set binfile ${testfile}
|
||||
+
|
||||
+if { [istarget ia64-*] } then {
|
||||
+ verbose "compiling source file now....."
|
||||
+ # Build the shared libraries this test case needs.
|
||||
+ if { [ ltrace_compile "${srcdir}/${subdir}/${testfile}.s" "${srcdir}/${subdir}/${binfile}" executable {debug} ] != "" } {
|
||||
+ send_user "Testcase compile failed, so all tests in this file will automatically fail\n."
|
||||
+ }
|
||||
+
|
||||
+ # Run PUT for ltarce.
|
||||
+ set exec_output [ltrace_runtest $srcdir/$subdir $srcdir/$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
|
||||
+ }
|
||||
+
|
||||
+ catch "exec sh -c {grep SIGILL ${srcdir}/${subdir}/${testfile}.ltrace | wc -l ;exit}" output
|
||||
+ if { $output == 0 } then {
|
||||
+ pass "ltrace did interpret SIGILL as breakpoint."
|
||||
+ } else {
|
||||
+ fail "ltrace failed to interpret SIGILL as breakpoint."
|
||||
+ }
|
||||
+}
|
||||
diff -Nurp ltrace-0.5-orig/testsuite/ltrace.torture/ia64-sigill.s ltrace-0.5/testsuite/ltrace.torture/ia64-sigill.s
|
||||
--- ltrace-0.5-orig/testsuite/ltrace.torture/ia64-sigill.s 1969-12-31 19:00:00.000000000 -0500
|
||||
+++ ltrace-0.5/testsuite/ltrace.torture/ia64-sigill.s 2007-05-04 12:51:14.000000000 -0400
|
||||
@@ -0,0 +1,43 @@
|
||||
+ .file "pokus.c"
|
||||
+ .pred.safe_across_calls p1-p5,p16-p63
|
||||
+ .section .rodata
|
||||
+ .align 8
|
||||
+.LC0:
|
||||
+ stringz ""
|
||||
+ .text
|
||||
+ .align 16
|
||||
+ .global main#
|
||||
+ .proc main#
|
||||
+main:
|
||||
+ .prologue 14, 32
|
||||
+ .save ar.pfs, r33
|
||||
+ alloc r33 = ar.pfs, 0, 4, 1, 0
|
||||
+ .vframe r34
|
||||
+ mov r34 = r12
|
||||
+ mov r35 = r1
|
||||
+ .save rp, r32
|
||||
+ mov r32 = b0
|
||||
+ .body
|
||||
+ addl r36 = @ltoffx(.LC0), r1
|
||||
+ ;;
|
||||
+ ld8.mov r36 = [r36], .LC0
|
||||
+ br.call.sptk.many b0 = printf#
|
||||
+ nop.b 0x0
|
||||
+ nop.b 0x1
|
||||
+ nop.b 0x2
|
||||
+ nop.b 0x0
|
||||
+ nop.b 0x1
|
||||
+ nop.b 0x2
|
||||
+ mov r1 = r35
|
||||
+ addl r14 = 234, r0
|
||||
+ ;;
|
||||
+ mov r8 = r14
|
||||
+ mov ar.pfs = r33
|
||||
+ mov b0 = r32
|
||||
+ .restore sp
|
||||
+ mov r12 = r34
|
||||
+ br.ret.sptk.many b0
|
||||
+ ;;
|
||||
+ .endp main#
|
||||
+ .section .note.GNU-stack,"",@progbits
|
||||
+ .ident "GCC: (GNU) 3.4.6 20060404 (Red Hat 3.4.6-3)"
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
13571
ltrace-0.6.0-abi.patch
13571
ltrace-0.6.0-abi.patch
File diff suppressed because it is too large
Load Diff
@ -1,652 +0,0 @@
|
||||
diff --git a/lens_default.c b/lens_default.c
|
||||
index f59d328..81025b1 100644
|
||||
--- a/lens_default.c
|
||||
+++ b/lens_default.c
|
||||
@@ -63,7 +63,7 @@ READER(read_double, double)
|
||||
int##BITS##_t i = l; \
|
||||
switch (format) { \
|
||||
case INT_FMT_unknown: \
|
||||
- if (i < -10000 || i > 10000) \
|
||||
+ if (l < -10000 || l > 10000) \
|
||||
case INT_FMT_x: \
|
||||
return fprintf(stream, "%#"PRIx##BITS, i); \
|
||||
case INT_FMT_i: \
|
||||
diff --git a/sysdeps/linux-gnu/ia64/breakpoint.c b/sysdeps/linux-gnu/ia64/breakpoint.c
|
||||
index a0bfaf9..a5071b8 100644
|
||||
--- a/sysdeps/linux-gnu/ia64/breakpoint.c
|
||||
+++ b/sysdeps/linux-gnu/ia64/breakpoint.c
|
||||
@@ -2,11 +2,12 @@
|
||||
* -Ian Wienand <ianw@gelato.unsw.edu.au> 10/3/2005
|
||||
*/
|
||||
|
||||
-#include "config.h"
|
||||
-
|
||||
#include <sys/ptrace.h>
|
||||
#include <string.h>
|
||||
-#include "common.h"
|
||||
+#include <assert.h>
|
||||
+
|
||||
+#include "breakpoint.h"
|
||||
+#include "debug.h"
|
||||
|
||||
static long long
|
||||
extract_bit_field(char *bundle, int from, int len) {
|
||||
@@ -161,9 +162,7 @@ arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp)
|
||||
|
||||
debug(1, "Enable Breakpoint at %p)", sbp->addr);
|
||||
|
||||
- if (slotnum > 2)
|
||||
- printf
|
||||
- ("Can't insert breakpoint for slot numbers greater than 2.");
|
||||
+ assert(slotnum <= 2);
|
||||
|
||||
addr &= ~0x0f;
|
||||
bundle.ubundle[0] = ptrace(PTRACE_PEEKTEXT, pid, addr, 0);
|
||||
diff --git a/sysdeps/linux-gnu/ia64/plt.c b/sysdeps/linux-gnu/ia64/plt.c
|
||||
index 323df65..76a4aac 100644
|
||||
--- a/sysdeps/linux-gnu/ia64/plt.c
|
||||
+++ b/sysdeps/linux-gnu/ia64/plt.c
|
||||
@@ -1,6 +1,8 @@
|
||||
#include <gelf.h>
|
||||
+
|
||||
#include "proc.h"
|
||||
#include "common.h"
|
||||
+#include "library.h"
|
||||
|
||||
/* A bundle is 128 bits */
|
||||
#define BUNDLE_SIZE 16
|
||||
@@ -36,7 +38,7 @@ arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) {
|
||||
unsigned long addr =
|
||||
lte->plt_addr + (4 * BUNDLE_SIZE) + (BUNDLE_SIZE * entries) +
|
||||
(2 * ndx * BUNDLE_SIZE);
|
||||
- debug(3, "Found PLT %d entry at %lx\n", ndx, addr);
|
||||
+ debug(3, "Found PLT %zd entry at %lx\n", ndx, addr);
|
||||
|
||||
return addr;
|
||||
}
|
||||
diff --git a/breakpoints.c b/breakpoints.c
|
||||
index e7120ee..3eee38b 100644
|
||||
--- a/breakpoints.c
|
||||
+++ b/breakpoints.c
|
||||
@@ -302,35 +302,6 @@ enable_all_breakpoints(Process *proc)
|
||||
dict_apply_to_all(proc->breakpoints, enable_bp_cb,
|
||||
proc);
|
||||
}
|
||||
-#ifdef __mips__
|
||||
- {
|
||||
- /*
|
||||
- * I'm sure there is a nicer way to do this. We need to
|
||||
- * insert breakpoints _after_ the child has been started.
|
||||
- */
|
||||
- struct library_symbol *sym;
|
||||
- struct library_symbol *new_sym;
|
||||
- sym=proc->list_of_symbols;
|
||||
- while(sym){
|
||||
- void *addr= sym2addr(proc,sym);
|
||||
- if(!addr){
|
||||
- sym=sym->next;
|
||||
- continue;
|
||||
- }
|
||||
- if(dict_find_entry(proc->breakpoints,addr)){
|
||||
- sym=sym->next;
|
||||
- continue;
|
||||
- }
|
||||
- debug(2,"inserting bp %p %s",addr,sym->name);
|
||||
- new_sym=malloc(sizeof(*new_sym) + strlen(sym->name) + 1);
|
||||
- memcpy(new_sym,sym,sizeof(*new_sym) + strlen(sym->name) + 1);
|
||||
- new_sym->next=proc->list_of_symbols;
|
||||
- proc->list_of_symbols=new_sym;
|
||||
- insert_breakpoint(proc, addr, new_sym);
|
||||
- sym=sym->next;
|
||||
- }
|
||||
- }
|
||||
-#endif
|
||||
}
|
||||
|
||||
static void
|
||||
diff --git a/handle_event.c b/handle_event.c
|
||||
index 5b6cc40..1720cb3 100644
|
||||
--- a/handle_event.c
|
||||
+++ b/handle_event.c
|
||||
@@ -232,6 +232,7 @@ pending_new_remove(pid_t pid) {
|
||||
debug(DEBUG_FUNCTION, "pending_new_remove(%d)", pid);
|
||||
|
||||
p = pending_news;
|
||||
+ pred = NULL;
|
||||
if (p->pid == pid) {
|
||||
pending_news = p->next;
|
||||
free(p);
|
||||
@@ -592,25 +593,6 @@ handle_breakpoint(Event *event)
|
||||
|
||||
for (i = event->proc->callstack_depth - 1; i >= 0; i--) {
|
||||
if (brk_addr == event->proc->callstack[i].return_addr) {
|
||||
-#if defined(__mips__)
|
||||
- void *addr = NULL;
|
||||
- struct library_symbol *sym= event->proc->callstack[i].c_un.libfunc;
|
||||
- struct library_symbol *new_sym;
|
||||
- assert(sym);
|
||||
- addr = sym2addr(event->proc, sym);
|
||||
- sbp = dict_find_entry(leader->breakpoints, addr);
|
||||
- if (sbp) {
|
||||
- if (addr != sbp->addr) {
|
||||
- insert_breakpoint(event->proc, addr, sym);
|
||||
- }
|
||||
- } else {
|
||||
- new_sym=malloc(sizeof(*new_sym) + strlen(sym->name) + 1);
|
||||
- memcpy(new_sym,sym,sizeof(*new_sym) + strlen(sym->name) + 1);
|
||||
- new_sym->next = leader->list_of_symbols;
|
||||
- leader->list_of_symbols = new_sym;
|
||||
- insert_breakpoint(event->proc, addr, new_sym);
|
||||
- }
|
||||
-#endif
|
||||
for (j = event->proc->callstack_depth - 1; j > i; j--) {
|
||||
callstack_pop(event->proc);
|
||||
}
|
||||
diff --git a/ltrace-elf.c b/ltrace-elf.c
|
||||
index c8667a7..bc99c6a 100644
|
||||
--- a/ltrace-elf.c
|
||||
+++ b/ltrace-elf.c
|
||||
@@ -50,10 +50,6 @@
|
||||
#include "debug.h"
|
||||
#include "options.h"
|
||||
|
||||
-#ifdef PLT_REINITALISATION_BP
|
||||
-extern char *PLTs_initialized_by_here;
|
||||
-#endif
|
||||
-
|
||||
#ifndef ARCH_HAVE_LTELF_DATA
|
||||
int
|
||||
arch_elf_init(struct ltelf *lte, struct library *lib)
|
||||
diff --git a/ltrace.1 b/ltrace.1
|
||||
index 604f4da..fb64289 100644
|
||||
--- a/ltrace.1
|
||||
+++ b/ltrace.1
|
||||
@@ -7,7 +7,7 @@ ltrace \- A library call tracer
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B ltrace
|
||||
-.I "[-bCfghiLrStttV] [-a column] [-A maxelts] [-D level] [-e expr] [-l filename] [-n nr] [-o filename] [-p pid] ... [-s strsize] [-u username] [-w count] [-X extern] [-x extern] ... [--align=column] [--debug=level] [--demangle] [--help] [--indent=nr] [--library=filename] [--no-signals] [--output=filename] [--version] [--where=NR] [command [arg ...]]"
|
||||
+.I "[-bCfghiLrStttV] [-a column] [-A maxelts] [-D level] [-e expr] [-l filename] [-n nr] [-o filename] [-p pid] ... [-s strsize] [-u username] [-w count] [-x extern] ... [--align=column] [--debug=level] [--demangle] [--help] [--indent=nr] [--library=filename] [--no-signals] [--output=filename] [--version] [--where=NR] [command [arg ...]]"
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B ltrace
|
||||
@@ -158,14 +158,6 @@ correct execution of setuid and/or setgid binaries.
|
||||
Show backtrace of NR stack frames for each traced function. This option enabled
|
||||
only if libunwind support was enabled at compile time.
|
||||
.TP
|
||||
-.I \-X extern
|
||||
-Some architectures need to know where to set a breakpoint that will be hit
|
||||
-after the dynamic linker has run. If this flag is used, then the breakpoint
|
||||
-is set at
|
||||
-.IR extern ,
|
||||
-which must be an external function. By default, '_start' is used.
|
||||
-NOTE: this flag is only available on the architectures that need it.
|
||||
-.TP
|
||||
.I \-x filter
|
||||
A qualifying expression which modifies which symbol table entry points
|
||||
to trace. The format of the filter expression is described in the
|
||||
diff --git a/options.c b/options.c
|
||||
index 8dce7f8..b9472a8 100644
|
||||
--- a/options.c
|
||||
+++ b/options.c
|
||||
@@ -50,12 +50,6 @@ struct opt_p_t *opt_p = NULL; /* attach to process with a given pid */
|
||||
/* List of filenames give to option -F: */
|
||||
struct opt_F_t *opt_F = NULL; /* alternate configuration file(s) */
|
||||
|
||||
-#ifdef PLT_REINITALISATION_BP
|
||||
-/* Set a break on the routine named here in order to re-initialize breakpoints
|
||||
- after all the PLTs have been initialzed */
|
||||
-char *PLTs_initialized_by_here = PLT_REINITALISATION_BP;
|
||||
-#endif
|
||||
-
|
||||
static void
|
||||
err_usage(void) {
|
||||
fprintf(stderr, "Try `%s --help' for more information\n", progname);
|
||||
@@ -78,7 +72,6 @@ usage(void) {
|
||||
" -e expr modify which events to trace.\n"
|
||||
" -f trace children (fork() and clone()).\n"
|
||||
" -F, --config=FILE load alternate configuration file (may be repeated).\n"
|
||||
- " -g, --no-plt disable breakpoints on PLT entries.\n"
|
||||
" -h, --help display this help and exit.\n"
|
||||
" -i print instruction pointer at time of library call.\n"
|
||||
" -l, --library=FILE print library calls from this library only.\n"
|
||||
@@ -97,9 +90,6 @@ usage(void) {
|
||||
" -w=NR, --where=NR print backtrace showing NR stack frames at most.\n"
|
||||
#endif /* defined(HAVE_LIBUNWIND) */
|
||||
" -x NAME treat the global NAME like a library subroutine.\n"
|
||||
-#ifdef PLT_REINITALISATION_BP
|
||||
- " -X NAME same as -x; and PLT's will be initialized by here.\n"
|
||||
-#endif
|
||||
"\nReport bugs to ltrace-devel@lists.alioth.debian.org\n",
|
||||
progname);
|
||||
}
|
||||
@@ -560,14 +550,6 @@ process_options(int argc, char **argv)
|
||||
options.bt_depth = atoi(optarg);
|
||||
break;
|
||||
#endif /* defined(HAVE_LIBUNWIND) */
|
||||
- case 'X':
|
||||
-#ifdef PLT_REINITALISATION_BP
|
||||
- PLTs_initialized_by_here = optarg;
|
||||
-#else
|
||||
- fprintf(stderr, "WARNING: \"-X\" not used for this "
|
||||
- "architecture: assuming you meant \"-x\"\n");
|
||||
-#endif
|
||||
- /* Fall Thru */
|
||||
|
||||
case 'x':
|
||||
parse_filter_chain(optarg, &options.static_filter);
|
||||
diff --git a/sysdeps/linux-gnu/ppc/arch.h b/sysdeps/linux-gnu/ppc/arch.h
|
||||
index 846961e..2d0ad65 100644
|
||||
--- a/sysdeps/linux-gnu/ppc/arch.h
|
||||
+++ b/sysdeps/linux-gnu/ppc/arch.h
|
||||
@@ -37,8 +37,6 @@
|
||||
#define ARCH_SUPPORTS_OPD
|
||||
#endif
|
||||
|
||||
-#define PLT_REINITALISATION_BP "_start"
|
||||
-
|
||||
#define ARCH_ENDIAN_BIG
|
||||
#define ARCH_HAVE_ATOMIC_SINGLESTEP
|
||||
#define ARCH_HAVE_ADD_PLT_ENTRY
|
||||
diff --git a/Makefile.am b/Makefile.am
|
||||
index 177a498..47161f8 100644
|
||||
--- a/Makefile.am
|
||||
+++ b/Makefile.am
|
||||
@@ -85,6 +85,7 @@ noinst_HEADERS = \
|
||||
type.h \
|
||||
value.h \
|
||||
value_dict.h \
|
||||
+ callback.h \
|
||||
expr.h \
|
||||
fetch.h \
|
||||
vect.h \
|
||||
diff --git a/callback.h b/callback.h
|
||||
new file mode 100644
|
||||
index 0000000..31e5c8f
|
||||
--- /dev/null
|
||||
+++ b/callback.h
|
||||
@@ -0,0 +1,50 @@
|
||||
+/*
|
||||
+ * This file is part of ltrace.
|
||||
+ * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 2 of the
|
||||
+ * License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful, but
|
||||
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, write to the Free Software
|
||||
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
+ * 02110-1301 USA
|
||||
+ */
|
||||
+
|
||||
+#ifndef _CALLBACK_H_
|
||||
+#define _CALLBACK_H_
|
||||
+
|
||||
+/* Notes on the iteration interface used across ltrace. Typically the
|
||||
+ * iteration function looks something like this:
|
||||
+ *
|
||||
+ * foo *each_foo(foo *start_after,
|
||||
+ * enum callback_status (*cb)(foo *f, void *data),
|
||||
+ * void *data);
|
||||
+ *
|
||||
+ * The iteration starts after the element designated by START_AFTER,
|
||||
+ * or at the first element if START_AFTER is NULL. CB is then called
|
||||
+ * for each element of the collection. DATA is passed verbatim to CB.
|
||||
+ * If CB returns CBS_STOP, the iteration stops and the current element
|
||||
+ * is returned. That element can then be passed as START_AFTER to
|
||||
+ * restart the iteration. NULL is returned when iteration ends.
|
||||
+ *
|
||||
+ * CBS_FAIL is not currently handled, and essentially means the same
|
||||
+ * thing as CBS_STOP. There's no provision for returning error
|
||||
+ * states. Errors need to be signaled to the caller via DATA,
|
||||
+ * together with any other data that the callback needs.
|
||||
+ */
|
||||
+enum callback_status {
|
||||
+ CBS_STOP, /* The iteration should stop. */
|
||||
+ CBS_CONT, /* The iteration should continue. */
|
||||
+ CBS_FAIL, /* There was an error. The iteration should stop
|
||||
+ * and return error. */
|
||||
+};
|
||||
+
|
||||
+#endif /* _CALLBACK_H_ */
|
||||
diff --git a/filter.c b/filter.c
|
||||
index 003010d..bf77b76 100644
|
||||
--- a/filter.c
|
||||
+++ b/filter.c
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "filter.h"
|
||||
#include "library.h"
|
||||
+#include "callback.h"
|
||||
|
||||
void
|
||||
filter_init(struct filter *filt)
|
||||
diff --git a/forward.h b/forward.h
|
||||
index e4233e5..8c03319 100644
|
||||
--- a/forward.h
|
||||
+++ b/forward.h
|
||||
@@ -12,3 +12,4 @@ struct param;
|
||||
struct param_enum;
|
||||
struct value;
|
||||
struct value_dict;
|
||||
+struct filter;
|
||||
diff --git a/library.c b/library.c
|
||||
index 2ce3427..cbd4a35 100644
|
||||
--- a/library.c
|
||||
+++ b/library.c
|
||||
@@ -25,8 +25,9 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "library.h"
|
||||
-#include "proc.h" // for enum callback_status
|
||||
+#include "callback.h"
|
||||
#include "debug.h"
|
||||
+#include "dict.h"
|
||||
#include "backend.h" // for arch_library_symbol_init, arch_library_init
|
||||
|
||||
#ifndef ARCH_HAVE_LIBRARY_DATA
|
||||
diff --git a/library.h b/library.h
|
||||
index 876a533..f207502 100644
|
||||
--- a/library.h
|
||||
+++ b/library.h
|
||||
@@ -23,6 +23,7 @@
|
||||
#define _LIBRARY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
+#include "callback.h"
|
||||
#include "sysdep.h"
|
||||
|
||||
struct Process;
|
||||
@@ -144,9 +145,8 @@ void library_set_soname(struct library *lib,
|
||||
void library_set_pathname(struct library *lib,
|
||||
const char *new_name, int own_name);
|
||||
|
||||
-/* Iterate through list of symbols of library LIB. Restarts are
|
||||
- * supported via START_AFTER (see each_process for details of
|
||||
- * iteration interface). */
|
||||
+/* Iterate through list of symbols of library LIB. See callback.h for
|
||||
+ * notes on this interface. */
|
||||
struct library_symbol *library_each_symbol
|
||||
(struct library *lib, struct library_symbol *start_after,
|
||||
enum callback_status (*cb)(struct library_symbol *, void *),
|
||||
diff --git a/options.c b/options.c
|
||||
index b9472a8..87dddb0 100644
|
||||
--- a/options.c
|
||||
+++ b/options.c
|
||||
@@ -52,7 +52,7 @@ struct opt_F_t *opt_F = NULL; /* alternate configuration file(s) */
|
||||
|
||||
static void
|
||||
err_usage(void) {
|
||||
- fprintf(stderr, "Try `%s --help' for more information\n", progname);
|
||||
+ fprintf(stderr, "Try `%s --help' for more information.\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ search_for_command(char *filename) {
|
||||
m = n = strlen(path);
|
||||
}
|
||||
if (n + strlen(filename) + 1 >= PATH_MAX) {
|
||||
- fprintf(stderr, "Error: filename too long\n");
|
||||
+ fprintf(stderr, "Error: filename too long.\n");
|
||||
exit(1);
|
||||
}
|
||||
strncpy(pathname, path, n);
|
||||
@@ -173,7 +173,7 @@ add_filter_rule(struct filter *filt, const char *expr,
|
||||
struct filter_lib_matcher *matcher = malloc(sizeof(*matcher));
|
||||
|
||||
if (rule == NULL || matcher == NULL) {
|
||||
- fprintf(stderr, "rule near '%s' will be ignored: %s\n",
|
||||
+ fprintf(stderr, "Rule near '%s' will be ignored: %s.\n",
|
||||
expr, strerror(errno));
|
||||
fail:
|
||||
free(rule);
|
||||
@@ -193,7 +193,7 @@ add_filter_rule(struct filter *filt, const char *expr,
|
||||
if (status != 0) {
|
||||
char buf[100];
|
||||
regerror(status, &symbol_re, buf, sizeof buf);
|
||||
- fprintf(stderr, "rule near '%s' will be ignored: %s\n",
|
||||
+ fprintf(stderr, "Rule near '%s' will be ignored: %s.\n",
|
||||
expr, buf);
|
||||
goto fail;
|
||||
}
|
||||
@@ -301,8 +301,8 @@ parse_filter(struct filter *filt, char *expr)
|
||||
/* /XXX@YYY/ is the same as
|
||||
* /XXX/@/YYY/. */
|
||||
if (libend[0] != '/')
|
||||
- fprintf(stderr, "unmatched '/'"
|
||||
- " in symbol name\n");
|
||||
+ fprintf(stderr, "Unmatched '/'"
|
||||
+ " in symbol name.\n");
|
||||
else
|
||||
*libend-- = 0;
|
||||
}
|
||||
@@ -339,7 +339,7 @@ recursive_parse_chain(char *expr)
|
||||
{
|
||||
struct filter *filt = malloc(sizeof(*filt));
|
||||
if (filt == NULL) {
|
||||
- fprintf(stderr, "(part of) filter will be ignored: '%s': %s\n",
|
||||
+ fprintf(stderr, "(Part of) filter will be ignored: '%s': %s.\n",
|
||||
expr, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
@@ -359,7 +359,7 @@ parse_filter_chain(const char *expr, struct filter **retp)
|
||||
{
|
||||
char *str = strdup(expr);
|
||||
if (str == NULL) {
|
||||
- fprintf(stderr, "filter '%s' will be ignored: %s\n",
|
||||
+ fprintf(stderr, "Filter '%s' will be ignored: %s.\n",
|
||||
expr, strerror(errno));
|
||||
return;
|
||||
}
|
||||
@@ -598,7 +598,8 @@ process_options(int argc, char **argv)
|
||||
err_usage();
|
||||
}
|
||||
if (opt_r && opt_t) {
|
||||
- fprintf(stderr, "%s: Incompatible options -r and -t\n",
|
||||
+ fprintf(stderr,
|
||||
+ "%s: Options -r and -t can't be used together\n",
|
||||
progname);
|
||||
err_usage();
|
||||
}
|
||||
diff --git a/options.h b/options.h
|
||||
index 3ffee71..0806928 100644
|
||||
--- a/options.h
|
||||
+++ b/options.h
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
-struct filter;
|
||||
+#include "forward.h"
|
||||
|
||||
struct options_t {
|
||||
int align; /* -a: default alignment column for results */
|
||||
diff --git a/proc.h b/proc.h
|
||||
index 64c37a9..b61e420 100644
|
||||
--- a/proc.h
|
||||
+++ b/proc.h
|
||||
@@ -34,20 +34,11 @@
|
||||
#include "ltrace.h"
|
||||
#include "dict.h"
|
||||
#include "sysdep.h"
|
||||
+#include "callback.h"
|
||||
|
||||
struct library;
|
||||
struct breakpoint;
|
||||
|
||||
-/* XXX Move this somewhere where it makes sense. When the mess in
|
||||
- * common.h is disentangled, that would actually be a good place for
|
||||
- * this. */
|
||||
-enum callback_status {
|
||||
- CBS_STOP, /* The iteration should stop. */
|
||||
- CBS_CONT, /* The iteration should continue. */
|
||||
- CBS_FAIL, /* There was an error. The iteration should stop
|
||||
- * and return error. */
|
||||
-};
|
||||
-
|
||||
struct event_handler {
|
||||
/* Event handler that overrides the default one. Should
|
||||
* return NULL if the event was handled, otherwise the
|
||||
@@ -184,28 +175,16 @@ Process * pid2proc(pid_t pid);
|
||||
* Returns 0 on success or a negative value on failure. */
|
||||
int process_clone(struct Process *retp, struct Process *proc, pid_t pid);
|
||||
|
||||
-/* Iterate through the processes that ltrace currently traces. CB is
|
||||
- * called for each process. Tasks are considered to be processes for
|
||||
- * the purpose of this iterator.
|
||||
- *
|
||||
- * Notes on this iteration interface: The iteration starts after the
|
||||
- * process designated by START_AFTER, or at the first process if
|
||||
- * START_AFTER is NULL. DATA is passed verbatim to CB. If CB returns
|
||||
- * CBS_STOP, the iteration stops and the current iterator is returned.
|
||||
- * That iterator can then be used to restart the iteration. NULL is
|
||||
- * returned when iteration ends.
|
||||
- *
|
||||
- * There's no provision for returning error states. Errors need to be
|
||||
- * signaled to the caller via DATA, together with any other data that
|
||||
- * the callback needs. */
|
||||
+/* Iterate through the processes that ltrace currently traces. Tasks
|
||||
+ * are considered to be processes for the purpose of this iterator.
|
||||
+ * See callback.h for notes on iteration interfaces. */
|
||||
Process *each_process(Process *start_after,
|
||||
enum callback_status (*cb)(struct Process *proc,
|
||||
void *data),
|
||||
void *data);
|
||||
|
||||
-/* Iterate through list of tasks of given process PROC. Restarts are
|
||||
- * supported via START_AFTER (see each_process for details of
|
||||
- * iteration interface). */
|
||||
+/* Iterate through list of tasks of given process PROC. See
|
||||
+ * callback.h for notes on iteration interfaces. */
|
||||
Process *each_task(struct Process *proc, struct Process *start_after,
|
||||
enum callback_status (*cb)(struct Process *proc,
|
||||
void *data),
|
||||
@@ -227,8 +206,8 @@ void proc_add_library(struct Process *proc, struct library *lib);
|
||||
* was found and unlinked, otherwise returns a negative value. */
|
||||
int proc_remove_library(struct Process *proc, struct library *lib);
|
||||
|
||||
-/* Iterate through the libraries of PROC. See each_process for
|
||||
- * detailed description of the iteration interface. */
|
||||
+/* Iterate through the libraries of PROC. See callback.h for notes on
|
||||
+ * iteration interfaces. */
|
||||
struct library *proc_each_library(struct Process *proc, struct library *start,
|
||||
enum callback_status (*cb)(struct Process *p,
|
||||
struct library *l,
|
||||
@@ -242,8 +221,8 @@ int proc_add_breakpoint(struct Process *proc, struct breakpoint *bp);
|
||||
* does not find BP in PROC, it's hard error guarded by assertion. */
|
||||
void proc_remove_breakpoint(struct Process *proc, struct breakpoint *bp);
|
||||
|
||||
-/* Iterate through the libraries of PROC. See each_process for
|
||||
- * detailed description of the iteration interface. */
|
||||
+/* Iterate through the breakpoints of PROC. See callback.h for notes
|
||||
+ * on iteration interfaces. */
|
||||
void *proc_each_breakpoint(struct Process *proc, void *start,
|
||||
enum callback_status (*cb)(struct Process *proc,
|
||||
struct breakpoint *bp,
|
||||
diff --git a/sysdeps/linux-gnu/x86/arch.h b/sysdeps/linux-gnu/x86/arch.h
|
||||
index 77a09d7..329cfba 100644
|
||||
--- a/sysdeps/linux-gnu/x86/arch.h
|
||||
+++ b/sysdeps/linux-gnu/x86/arch.h
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ltrace.
|
||||
- * Copyright (C) 2011 Petr Machata
|
||||
+ * Copyright (C) 2011, 2012 Petr Machata
|
||||
* Copyright (C) 2006 Ian Wienand
|
||||
* Copyright (C) 2004 Juan Cespedes
|
||||
*
|
||||
@@ -34,7 +34,3 @@
|
||||
#endif
|
||||
#define LT_ELFCLASS2 ELFCLASS32
|
||||
#define LT_ELF_MACHINE2 EM_386
|
||||
-
|
||||
-/* __NR_fork, __NR_clone, __NR_clone2, __NR_vfork and __NR_execve
|
||||
- from asm-i386/unistd.h. */
|
||||
-#define FORK_EXEC_SYSCALLS , { 2, 120, -1, 190, 11 }
|
||||
diff --git a/testsuite/ltrace.main/parameters.c b/testsuite/ltrace.main/parameters.c
|
||||
index 158fdd7..44d54b2 100644
|
||||
--- a/testsuite/ltrace.main/parameters.c
|
||||
+++ b/testsuite/ltrace.main/parameters.c
|
||||
@@ -190,7 +190,7 @@ main ()
|
||||
"%c %d %g %d %g %c %d "
|
||||
"%hd %d %c %g %g %g "
|
||||
"%ld %g %g %g %g",
|
||||
- 1, 2, 3, 4.0, '5', 6, 7.0,
|
||||
+ 1, 2, 3L, 4.0, '5', 6, 7.0,
|
||||
'8', 9, 10.0, 11, 12.0, 'A', 14,
|
||||
(short)15, 16, 'B', 18.0, 19.0, 20.0,
|
||||
21L, 22.0, 23.0, 24.0, 25.0);
|
||||
diff --git a/vect.c b/vect.c
|
||||
index f2e58b2..7dae847 100644
|
||||
--- a/vect.c
|
||||
+++ b/vect.c
|
||||
@@ -134,3 +134,25 @@ vect_destroy(struct vect *vec, void (*dtor)(void *emt, void *data), void *data)
|
||||
}
|
||||
free(vec->data);
|
||||
}
|
||||
+
|
||||
+void *
|
||||
+vect_each(struct vect *vec, void *start_after,
|
||||
+ enum callback_status (*cb)(void *, void *), void *data)
|
||||
+{
|
||||
+ size_t i = start_after == NULL ? 0
|
||||
+ : ((start_after - vec->data) / vec->elt_size) + 1;
|
||||
+
|
||||
+ for (; i < vec->size; ++i) {
|
||||
+ void *slt = slot(vec, i);
|
||||
+ switch ((*cb)(slt, data)) {
|
||||
+ case CBS_FAIL:
|
||||
+ /* XXX handle me */
|
||||
+ case CBS_STOP:
|
||||
+ return slt;
|
||||
+ case CBS_CONT:
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
diff --git a/vect.h b/vect.h
|
||||
index 50401bb..c07235f 100644
|
||||
--- a/vect.h
|
||||
+++ b/vect.h
|
||||
@@ -22,6 +22,9 @@
|
||||
#define VECT_H
|
||||
|
||||
#include <stddef.h>
|
||||
+#include <assert.h>
|
||||
+
|
||||
+#include "callback.h"
|
||||
|
||||
/* Vector is an array that can grow as needed to accommodate the data
|
||||
* that it needs to hold. ELT_SIZE is also used as an elementary
|
||||
@@ -122,4 +125,22 @@ void vect_destroy(struct vect *vec,
|
||||
DATA); \
|
||||
} while (0)
|
||||
|
||||
+/* Iterate through vector VEC. See callback.h for notes on iteration
|
||||
+ * interfaces. */
|
||||
+void *vect_each(struct vect *vec, void *start_after,
|
||||
+ enum callback_status (*cb)(void *, void *), void *data);
|
||||
+
|
||||
+#define VECT_EACH(VECP, ELT_TYPE, START_AFTER, CB, DATA) \
|
||||
+ /* xxx GCC-ism necessary to get in the safety latches. */ \
|
||||
+ ({ \
|
||||
+ assert((VECP)->elt_size == sizeof(ELT_TYPE)); \
|
||||
+ /* Check that CB is typed properly. */ \
|
||||
+ enum callback_status (*_cb)(ELT_TYPE *, void *) = CB; \
|
||||
+ ELT_TYPE *start_after = (START_AFTER); \
|
||||
+ (ELT_TYPE *)vect_each((VECP), start_after, \
|
||||
+ (enum callback_status \
|
||||
+ (*)(void *, void *))_cb, \
|
||||
+ DATA); \
|
||||
+ })
|
||||
+
|
||||
#endif /* VECT_H */
|
||||
@ -1,12 +0,0 @@
|
||||
diff --git a/testsuite/ltrace.minor/trace-clone.c b/testsuite/ltrace.minor/trace-clone.c
|
||||
index a1ccb22..6e1c809 100644
|
||||
--- a/testsuite/ltrace.minor/trace-clone.c
|
||||
+++ b/testsuite/ltrace.minor/trace-clone.c
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
This file was written by Yao Qi <qiyao@cn.ibm.com>. */
|
||||
|
||||
+#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,26 +0,0 @@
|
||||
diff --git a/options.c b/options.c
|
||||
index d5edc1a..8dce7f8 100644
|
||||
--- a/options.c
|
||||
+++ b/options.c
|
||||
@@ -494,9 +494,19 @@ process_options(int argc, char **argv)
|
||||
case 'L':
|
||||
libcalls = 0;
|
||||
break;
|
||||
- case 'n':
|
||||
- options.indent = atoi(optarg);
|
||||
+ case 'n': {
|
||||
+ char *endptr;
|
||||
+ long int l = strtol(optarg, &endptr, 0);
|
||||
+ /* Arbitrary cut-off. Nobody needs to indent
|
||||
+ * more than, say, 8, anyway. */
|
||||
+ if (l < 0 || l > 20 || *optarg == 0 || *endptr != 0) {
|
||||
+ fprintf(stderr, "Invalid argument to -n: '%s'."
|
||||
+ " Use integer 0..20.\n", optarg);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ options.indent = (int)l;
|
||||
break;
|
||||
+ }
|
||||
case 'o':
|
||||
options.output = fopen(optarg, "w");
|
||||
if (!options.output) {
|
||||
@ -1,86 +0,0 @@
|
||||
diff --git a/Makefile.am b/Makefile.am
|
||||
index 256c940..593e943 100644
|
||||
--- a/Makefile.am
|
||||
+++ b/Makefile.am
|
||||
@@ -35,6 +35,7 @@ libltrace_la_LIBADD = \
|
||||
$(libelf_LIBS) \
|
||||
$(liberty_LIBS) \
|
||||
$(libsupcxx_LIBS) \
|
||||
+ $(libstdcxx_LIBS) \
|
||||
$(libunwind_LIBS) \
|
||||
$(libunwind_ptrace_LIBS) \
|
||||
$(libunwind_arch_LIBS) \
|
||||
diff --git a/common.h b/common.h
|
||||
index 7fffa76..b84a5d1 100644
|
||||
--- a/common.h
|
||||
+++ b/common.h
|
||||
@@ -16,7 +16,10 @@
|
||||
#include "read_config_file.h"
|
||||
#include "proc.h"
|
||||
|
||||
-#if defined HAVE_LIBIBERTY || defined HAVE_LIBSUPC__
|
||||
+#if defined HAVE_LIBSUPC__ || defined HAVE_LIBSTDC__
|
||||
+# define USE_CXA_DEMANGLE
|
||||
+#endif
|
||||
+#if defined HAVE_LIBIBERTY || defined USE_CXA_DEMANGLE
|
||||
# define USE_DEMANGLE
|
||||
#endif
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 707f8c5..1ec7242 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -82,6 +82,14 @@ AC_CHECK_LIB([supc++], [__cxa_demangle], [
|
||||
AC_SUBST(libsupcxx_LIBS)
|
||||
|
||||
|
||||
+# HAVE_LIBSTDC__
|
||||
+AC_CHECK_LIB([stdc++], [__cxa_demangle], [
|
||||
+ AC_DEFINE([HAVE_LIBSTDC__], [1], [we have libstdc++])
|
||||
+ libstdcxx_LIBS="-lstdc++"], [
|
||||
+ libstdcxx_LIBS=""])
|
||||
+AC_SUBST(libstdcxx_LIBS)
|
||||
+
|
||||
+
|
||||
dnl Check security_get_boolean_active availability.
|
||||
AC_CHECK_HEADERS(selinux/selinux.h)
|
||||
AC_CHECK_LIB(selinux, security_get_boolean_active)
|
||||
diff --git a/demangle.c b/demangle.c
|
||||
index 5825e28..26a5c7a 100644
|
||||
--- a/demangle.c
|
||||
+++ b/demangle.c
|
||||
@@ -15,9 +15,8 @@ static Dict *d = NULL;
|
||||
const char *
|
||||
my_demangle(const char *function_name) {
|
||||
const char *tmp, *fn_copy;
|
||||
-#if !defined HAVE_LIBIBERTY && defined HAVE_LIBSUPC__
|
||||
+#ifdef USE_CXA_DEMANGLE
|
||||
extern char *__cxa_demangle(const char *, char *, size_t *, int *);
|
||||
- int status = 0;
|
||||
#endif
|
||||
|
||||
debug(DEBUG_FUNCTION, "my_demangle(name=%s)", function_name);
|
||||
@@ -30,7 +29,8 @@ my_demangle(const char *function_name) {
|
||||
fn_copy = strdup(function_name);
|
||||
#ifdef HAVE_LIBIBERTY
|
||||
tmp = cplus_demangle(function_name, DMGL_ANSI | DMGL_PARAMS);
|
||||
-#elif defined HAVE_LIBSUPC__
|
||||
+#elif defined USE_CXA_DEMANGLE
|
||||
+ int status = 0;
|
||||
tmp = __cxa_demangle(function_name, NULL, NULL, &status);
|
||||
#endif
|
||||
if (!tmp)
|
||||
diff --git a/testsuite/ltrace.minor/demangle.exp b/testsuite/ltrace.minor/demangle.exp
|
||||
index c2d3aeb..9dd7694 100644
|
||||
--- a/testsuite/ltrace.minor/demangle.exp
|
||||
+++ b/testsuite/ltrace.minor/demangle.exp
|
||||
@@ -32,6 +32,9 @@ if [regexp {ELF from incompatible architecture} $exec_output] {
|
||||
} elseif [ regexp {Couldn't get .hash data} $exec_output ] {
|
||||
fail "Couldn't get .hash data!"
|
||||
return
|
||||
+} elseif [ regexp {invalid option} $exec_output ] {
|
||||
+ unsupported "Demangle support not compiled in."
|
||||
+ return
|
||||
}
|
||||
|
||||
# read function declarations from demangle.cpp and verify them in demangle.ltrace.
|
||||
@ -1,141 +0,0 @@
|
||||
diff --git a/common.h b/common.h
|
||||
index 2399e29..b6e10f2 100644
|
||||
--- a/common.h
|
||||
+++ b/common.h
|
||||
@@ -347,7 +347,6 @@ 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, struct breakpoint *sbp);
|
||||
extern void continue_after_vfork(Process * proc);
|
||||
-extern void ltrace_exiting(void);
|
||||
extern long gimme_arg(enum tof type, Process * proc, int arg_num, arg_type_info * info);
|
||||
extern void save_register_args(enum tof type, Process * proc);
|
||||
extern int umovestr(Process * proc, void * addr, int len, void * laddr);
|
||||
@@ -363,5 +362,21 @@ extern int task_kill (pid_t pid, int sig);
|
||||
* any platform-specific knowledge of why it could be so. */
|
||||
void trace_fail_warning(pid_t pid);
|
||||
|
||||
+/* A pair of functions called to initiate a detachment request when
|
||||
+ * ltrace is about to exit. Their job is to undo any effects that
|
||||
+ * tracing had and eventually detach process, perhaps by way of
|
||||
+ * installing a process handler.
|
||||
+ *
|
||||
+ * OS_LTRACE_EXITING_SIGHANDLER is called from a signal handler
|
||||
+ * context right after the signal was captured. It returns 1 if the
|
||||
+ * request was handled or 0 if it wasn't.
|
||||
+ *
|
||||
+ * If the call to OS_LTRACE_EXITING_SIGHANDLER didn't handle the
|
||||
+ * request, OS_LTRACE_EXITING is called when the next event is
|
||||
+ * generated. Therefore it's called in "safe" context, without
|
||||
+ * re-entrancy concerns, but it's only called after an even is
|
||||
+ * generated. */
|
||||
+int os_ltrace_exiting_sighandler(void);
|
||||
+void os_ltrace_exiting(void);
|
||||
|
||||
extern struct ltelf main_lte;
|
||||
diff --git a/handle_event.c b/handle_event.c
|
||||
index e3d3d0a..725f50d 100644
|
||||
--- a/handle_event.c
|
||||
+++ b/handle_event.c
|
||||
@@ -49,11 +49,12 @@ call_handler(Process * proc, Event * event)
|
||||
}
|
||||
|
||||
void
|
||||
-handle_event(Event *event) {
|
||||
+handle_event(Event *event)
|
||||
+{
|
||||
if (exiting == 1) {
|
||||
- exiting = 2;
|
||||
debug(1, "ltrace about to exit");
|
||||
- ltrace_exiting();
|
||||
+ os_ltrace_exiting();
|
||||
+ exiting = 2;
|
||||
}
|
||||
debug(DEBUG_FUNCTION, "handle_event(pid=%d, type=%d)",
|
||||
event->proc ? event->proc->pid : -1, event->type);
|
||||
diff --git a/libltrace.c b/libltrace.c
|
||||
index 19bfafd..777ad1b 100644
|
||||
--- a/libltrace.c
|
||||
+++ b/libltrace.c
|
||||
@@ -48,9 +48,14 @@ signal_alarm(int sig) {
|
||||
}
|
||||
|
||||
static void
|
||||
-signal_exit(int sig) {
|
||||
- exiting = 1;
|
||||
+signal_exit(int sig)
|
||||
+{
|
||||
debug(1, "Received interrupt signal; exiting...");
|
||||
+ if (exiting != 0)
|
||||
+ return;
|
||||
+
|
||||
+ exiting = 1 + !!os_ltrace_exiting_sighandler();
|
||||
+
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
signal(SIGALRM, signal_alarm);
|
||||
diff --git a/sysdeps/linux-gnu/events.c b/sysdeps/linux-gnu/events.c
|
||||
index 021192f..b6c12ef 100644
|
||||
--- a/sysdeps/linux-gnu/events.c
|
||||
+++ b/sysdeps/linux-gnu/events.c
|
||||
@@ -104,6 +104,8 @@ next_qd_event(void)
|
||||
return each_qd_event(&event_process_not_reenabling, NULL);
|
||||
}
|
||||
|
||||
+int linux_in_waitpid = 0;
|
||||
+
|
||||
Event *
|
||||
next_event(void)
|
||||
{
|
||||
@@ -124,7 +126,11 @@ next_event(void)
|
||||
debug(DEBUG_EVENT, "event: No more traced programs: exiting");
|
||||
exit(0);
|
||||
}
|
||||
+
|
||||
+ linux_in_waitpid = 1;
|
||||
pid = waitpid(-1, &status, __WALL);
|
||||
+ linux_in_waitpid = 0;
|
||||
+
|
||||
if (pid == -1) {
|
||||
if (errno == ECHILD) {
|
||||
debug(DEBUG_EVENT, "event: No more traced programs: exiting");
|
||||
diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c
|
||||
index 82a4154..9ecea1e 100644
|
||||
--- a/sysdeps/linux-gnu/trace.c
|
||||
+++ b/sysdeps/linux-gnu/trace.c
|
||||
@@ -314,8 +314,8 @@ task_stopped(Process * task, void * data)
|
||||
case ps_invalid:
|
||||
case ps_tracing_stop:
|
||||
case ps_zombie:
|
||||
- case ps_sleeping:
|
||||
return pcb_cont;
|
||||
+ case ps_sleeping:
|
||||
case ps_stop:
|
||||
case ps_other:
|
||||
return pcb_stop;
|
||||
@@ -1005,7 +1005,7 @@ continue_after_syscall(Process * proc, int sysnum, int ret_p)
|
||||
* detaches.
|
||||
*/
|
||||
void
|
||||
-ltrace_exiting(void)
|
||||
+os_ltrace_exiting(void)
|
||||
{
|
||||
struct opt_p_t * it;
|
||||
for (it = opt_p; it != NULL; it = it->next) {
|
||||
@@ -1019,6 +1019,17 @@ ltrace_exiting(void)
|
||||
}
|
||||
}
|
||||
|
||||
+int
|
||||
+os_ltrace_exiting_sighandler(void)
|
||||
+{
|
||||
+ extern int linux_in_waitpid;
|
||||
+ if (linux_in_waitpid) {
|
||||
+ os_ltrace_exiting();
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
size_t
|
||||
umovebytes(Process *proc, void *addr, void *laddr, size_t len) {
|
||||
|
||||
@ -1,203 +0,0 @@
|
||||
diff --git a/sysdeps/linux-gnu/alpha/arch.h b/sysdeps/linux-gnu/alpha/arch.h
|
||||
index 1107b5f..2dfeec7 100644
|
||||
--- a/sysdeps/linux-gnu/alpha/arch.h
|
||||
+++ b/sysdeps/linux-gnu/alpha/arch.h
|
||||
@@ -1,6 +1,7 @@
|
||||
#define BREAKPOINT_VALUE { 0x80, 0x00, 0x00, 0x00 }
|
||||
#define BREAKPOINT_LENGTH 4
|
||||
#define DECR_PC_AFTER_BREAK 4
|
||||
+#define ARCH_ENDIAN_LITTLE
|
||||
|
||||
#define LT_ELFCLASS ELFCLASS64
|
||||
#define LT_ELF_MACHINE EM_ALPHA
|
||||
diff --git a/sysdeps/linux-gnu/arm/arch.h b/sysdeps/linux-gnu/arm/arch.h
|
||||
index 8f2dfb3..e2a62ab 100644
|
||||
--- a/sysdeps/linux-gnu/arm/arch.h
|
||||
+++ b/sysdeps/linux-gnu/arm/arch.h
|
||||
@@ -6,6 +6,7 @@
|
||||
#define THUMB_BREAKPOINT_VALUE { 0x01, 0xde }
|
||||
#define THUMB_BREAKPOINT_LENGTH 2
|
||||
#define DECR_PC_AFTER_BREAK 0
|
||||
+#define ARCH_ENDIAN_LITTLE
|
||||
|
||||
#define LT_ELFCLASS ELFCLASS32
|
||||
#define LT_ELF_MACHINE EM_ARM
|
||||
diff --git a/sysdeps/linux-gnu/i386/arch.h b/sysdeps/linux-gnu/i386/arch.h
|
||||
index dc7383f..15f0d78 100644
|
||||
--- a/sysdeps/linux-gnu/i386/arch.h
|
||||
+++ b/sysdeps/linux-gnu/i386/arch.h
|
||||
@@ -1,6 +1,7 @@
|
||||
#define BREAKPOINT_VALUE {0xcc}
|
||||
#define BREAKPOINT_LENGTH 1
|
||||
#define DECR_PC_AFTER_BREAK 1
|
||||
+#define ARCH_ENDIAN_LITTLE
|
||||
|
||||
#define LT_ELFCLASS ELFCLASS32
|
||||
#define LT_ELF_MACHINE EM_386
|
||||
diff --git a/sysdeps/linux-gnu/ia64/arch.h b/sysdeps/linux-gnu/ia64/arch.h
|
||||
index 673047c..d7e0d23 100644
|
||||
--- a/sysdeps/linux-gnu/ia64/arch.h
|
||||
+++ b/sysdeps/linux-gnu/ia64/arch.h
|
||||
@@ -4,6 +4,7 @@
|
||||
#define BREAKPOINT_LENGTH 16
|
||||
#define BREAKPOINT_VALUE {0}
|
||||
#define DECR_PC_AFTER_BREAK 0
|
||||
+#define ARCH_ENDIAN_LITTLE
|
||||
|
||||
#define LT_ELFCLASS ELFCLASS64
|
||||
#define LT_ELF_MACHINE EM_IA_64
|
||||
diff --git a/sysdeps/linux-gnu/m68k/arch.h b/sysdeps/linux-gnu/m68k/arch.h
|
||||
index 1790d09..44fad89 100644
|
||||
--- a/sysdeps/linux-gnu/m68k/arch.h
|
||||
+++ b/sysdeps/linux-gnu/m68k/arch.h
|
||||
@@ -1,6 +1,7 @@
|
||||
#define BREAKPOINT_VALUE { 0x4e, 0x4f }
|
||||
#define BREAKPOINT_LENGTH 2
|
||||
#define DECR_PC_AFTER_BREAK 2
|
||||
+#define ARCH_ENDIAN_BIG
|
||||
|
||||
#define LT_ELFCLASS ELFCLASS32
|
||||
#define LT_ELF_MACHINE EM_68K
|
||||
diff --git a/sysdeps/linux-gnu/mipsel/arch.h b/sysdeps/linux-gnu/mipsel/arch.h
|
||||
index dd0ca35..45c4598 100644
|
||||
--- a/sysdeps/linux-gnu/mipsel/arch.h
|
||||
+++ b/sysdeps/linux-gnu/mipsel/arch.h
|
||||
@@ -1,6 +1,7 @@
|
||||
#define BREAKPOINT_VALUE { 0x0d, 0x00, 0x00, 0x00 }
|
||||
#define BREAKPOINT_LENGTH 4
|
||||
#define DECR_PC_AFTER_BREAK 0
|
||||
+#define ARCH_ENDIAN_LITTLE
|
||||
|
||||
#define LT_ELFCLASS ELFCLASS32
|
||||
#define LT_ELF_MACHINE EM_MIPS
|
||||
diff --git a/sysdeps/linux-gnu/ppc/arch.h b/sysdeps/linux-gnu/ppc/arch.h
|
||||
index 711b4a3..8b955e8 100644
|
||||
--- a/sysdeps/linux-gnu/ppc/arch.h
|
||||
+++ b/sysdeps/linux-gnu/ppc/arch.h
|
||||
@@ -14,7 +14,7 @@
|
||||
#define PLT_REINITALISATION_BP "_start"
|
||||
|
||||
/* Start of arch-specific functions. */
|
||||
-#define ARCH_HAVE_UMOVELONG
|
||||
+#define ARCH_ENDIAN_BIG
|
||||
|
||||
#define PPC_NOP { 0x60, 0x00, 0x00, 0x00 }
|
||||
#define PPC_NOP_LENGTH 4
|
||||
diff -up ltrace-0.6.0/sysdeps/linux-gnu/ppc/trace.c\~ ltrace-0.6.0/sysdeps/linux-gnu/ppc/trace.c
|
||||
--- ltrace-0.6.0/sysdeps/linux-gnu/ppc/trace.c~ 2011-02-14 16:48:25.000000000 +0100
|
||||
+++ ltrace-0.6.0/sysdeps/linux-gnu/ppc/trace.c 2011-09-03 00:18:14.518317665 +0200
|
||||
@@ -156,34 +156,3 @@ save_register_args(enum tof type, Proces
|
||||
memcpy(&arch->regs_copy, &arch->regs, sizeof(arch->regs));
|
||||
memcpy(&arch->fpregs_copy, &arch->fpregs, sizeof(arch->fpregs));
|
||||
}
|
||||
-
|
||||
-/* Read a single long from the process's memory address 'addr'. */
|
||||
-int
|
||||
-arch_umovelong (Process *proc, void *addr, long *result, arg_type_info *info) {
|
||||
- long pointed_to;
|
||||
-
|
||||
- errno = 0;
|
||||
-
|
||||
- pointed_to = ptrace (PTRACE_PEEKTEXT, proc->pid, addr, 0);
|
||||
-
|
||||
- if (pointed_to == -1 && errno)
|
||||
- return -errno;
|
||||
-
|
||||
- /* Since int's are 4-bytes (long is 8-bytes) in length for ppc64, we
|
||||
- need to shift the long values returned by ptrace to end up with
|
||||
- the correct value. */
|
||||
-
|
||||
- if (info) {
|
||||
- if (info->type == ARGTYPE_INT || (proc->mask_32bit && (info->type == ARGTYPE_POINTER
|
||||
- || info->type == ARGTYPE_STRING))) {
|
||||
- pointed_to = pointed_to >> 32;
|
||||
-
|
||||
- /* Make sure we have nothing in the upper word so we can
|
||||
- do a explicit cast from long to int later in the code. */
|
||||
- pointed_to &= 0x00000000ffffffff;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- *result = pointed_to;
|
||||
- return 0;
|
||||
-}
|
||||
diff --git a/sysdeps/linux-gnu/s390/arch.h b/sysdeps/linux-gnu/s390/arch.h
|
||||
index 5cf168c..c6fed74 100644
|
||||
--- a/sysdeps/linux-gnu/s390/arch.h
|
||||
+++ b/sysdeps/linux-gnu/s390/arch.h
|
||||
@@ -6,6 +6,7 @@
|
||||
#define BREAKPOINT_VALUE { 0x00, 0x01 }
|
||||
#define BREAKPOINT_LENGTH 2
|
||||
#define DECR_PC_AFTER_BREAK 2
|
||||
+#define ARCH_ENDIAN_BIG
|
||||
|
||||
#ifdef __s390x__
|
||||
#define LT_ELFCLASS ELFCLASS64
|
||||
diff --git a/sysdeps/linux-gnu/sparc/arch.h b/sysdeps/linux-gnu/sparc/arch.h
|
||||
index 75251b8..bec22ce 100644
|
||||
--- a/sysdeps/linux-gnu/sparc/arch.h
|
||||
+++ b/sysdeps/linux-gnu/sparc/arch.h
|
||||
@@ -1,6 +1,7 @@
|
||||
#define BREAKPOINT_VALUE {0x91, 0xd0, 0x20, 0x01}
|
||||
#define BREAKPOINT_LENGTH 4
|
||||
#define DECR_PC_AFTER_BREAK 0
|
||||
+#define ARCH_ENDIAN_BIG
|
||||
|
||||
#define LT_ELFCLASS ELFCLASS32
|
||||
#define LT_ELF_MACHINE EM_SPARC
|
||||
diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c
|
||||
index e4be465..9b0b980 100644
|
||||
--- a/sysdeps/linux-gnu/trace.c
|
||||
+++ b/sysdeps/linux-gnu/trace.c
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "common.h"
|
||||
+#include "config.h"
|
||||
|
||||
/* If the system headers did not provide the constants, hard-code the normal
|
||||
values. */
|
||||
@@ -54,15 +55,23 @@ umovelong (Process *proc, void *addr, long *result, arg_type_info *info) {
|
||||
if (pointed_to == -1 && errno)
|
||||
return -errno;
|
||||
|
||||
- *result = pointed_to;
|
||||
- if (info) {
|
||||
- switch(info->type) {
|
||||
- case ARGTYPE_INT:
|
||||
- *result &= 0x00000000ffffffffUL;
|
||||
- default:
|
||||
- break;
|
||||
- };
|
||||
+#if SIZEOF_LONG == 8
|
||||
+ if (info != NULL
|
||||
+ && (info->type == ARGTYPE_INT
|
||||
+ || (proc->mask_32bit
|
||||
+ && (info->type == ARGTYPE_POINTER
|
||||
+ || info->type == ARGTYPE_STRING)))) {
|
||||
+#if defined (ARCH_ENDIAN_LITTLE)
|
||||
+ pointed_to &= 0x00000000ffffffffUL;
|
||||
+#elif defined (ARCH_ENDIAN_BIG)
|
||||
+ pointed_to = (long)(((unsigned long)pointed_to) >> 32);
|
||||
+#else
|
||||
+# error arch.h has to define endianness
|
||||
+#endif
|
||||
}
|
||||
+#endif
|
||||
+
|
||||
+ *result = pointed_to;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
diff --git a/sysdeps/linux-gnu/x86_64/arch.h b/sysdeps/linux-gnu/x86_64/arch.h
|
||||
index 255395c..34376c4 100644
|
||||
--- a/sysdeps/linux-gnu/x86_64/arch.h
|
||||
+++ b/sysdeps/linux-gnu/x86_64/arch.h
|
||||
@@ -1,6 +1,7 @@
|
||||
#define BREAKPOINT_VALUE {0xcc}
|
||||
#define BREAKPOINT_LENGTH 1
|
||||
#define DECR_PC_AFTER_BREAK 1
|
||||
+#define ARCH_ENDIAN_LITTLE
|
||||
|
||||
#define LT_ELFCLASS ELFCLASS64
|
||||
#define LT_ELF_MACHINE EM_X86_64
|
||||
@ -1,63 +0,0 @@
|
||||
diff -up ltrace-0.6.0/ltrace-elf.c\~ ltrace-0.6.0/ltrace-elf.c
|
||||
--- ltrace-0.6.0/ltrace-elf.c~ 2011-02-14 16:48:25.000000000 +0100
|
||||
+++ ltrace-0.6.0/ltrace-elf.c 2011-02-14 18:13:03.000000000 +0100
|
||||
@@ -609,6 +609,7 @@ read_elf(Process *proc) {
|
||||
struct ltelf lte[MAX_LIBRARIES + 1];
|
||||
size_t i;
|
||||
struct opt_x_t *xptr;
|
||||
+ struct opt_x_t *opt_x_loc = opt_x;
|
||||
struct library_symbol **lib_tail = NULL;
|
||||
int exit_out = 0;
|
||||
int count = 0;
|
||||
@@ -722,11 +723,11 @@ read_elf(Process *proc) {
|
||||
main_cheat = (struct opt_x_t *)malloc(sizeof(struct opt_x_t));
|
||||
if (main_cheat == NULL)
|
||||
error(EXIT_FAILURE, 0, "Couldn't allocate memory");
|
||||
- main_cheat->next = opt_x;
|
||||
+ main_cheat->next = opt_x_loc;
|
||||
main_cheat->found = 0;
|
||||
main_cheat->name = PLTs_initialized_by_here;
|
||||
|
||||
- for (xptr = opt_x; xptr; xptr = xptr->next)
|
||||
+ for (xptr = opt_x_loc; xptr; xptr = xptr->next)
|
||||
if (strcmp(xptr->name, PLTs_initialized_by_here) == 0
|
||||
&& main_cheat) {
|
||||
free(main_cheat);
|
||||
@@ -734,7 +735,7 @@ read_elf(Process *proc) {
|
||||
break;
|
||||
}
|
||||
if (main_cheat)
|
||||
- opt_x = main_cheat;
|
||||
+ opt_x_loc = main_cheat;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
@@ -756,7 +757,7 @@ read_elf(Process *proc) {
|
||||
if (!addr)
|
||||
continue;
|
||||
|
||||
- for (xptr = opt_x; xptr; xptr = xptr->next)
|
||||
+ for (xptr = opt_x_loc; xptr; xptr = xptr->next)
|
||||
if (xptr->name && strcmp(xptr->name, name) == 0) {
|
||||
/* FIXME: Should be able to use &library_symbols as above. But
|
||||
when you do, none of the real library symbols cause breaks. */
|
||||
@@ -769,7 +770,7 @@ read_elf(Process *proc) {
|
||||
|
||||
unsigned found_count = 0;
|
||||
|
||||
- for (xptr = opt_x; xptr; xptr = xptr->next) {
|
||||
+ for (xptr = opt_x_loc; xptr; xptr = xptr->next) {
|
||||
if (xptr->found)
|
||||
continue;
|
||||
|
||||
@@ -791,7 +792,7 @@ read_elf(Process *proc) {
|
||||
}
|
||||
}
|
||||
|
||||
- for (xptr = opt_x; xptr; xptr = xptr->next)
|
||||
+ for (xptr = opt_x_loc; xptr; xptr = xptr->next)
|
||||
if ( ! xptr->found) {
|
||||
char *badthing = "WARNING";
|
||||
#ifdef PLT_REINITALISATION_BP
|
||||
|
||||
Diff finished. Mon Feb 14 18:13:11 2011
|
||||
@ -1,39 +0,0 @@
|
||||
diff --git a/output.c b/output.c
|
||||
index ac8c9d0..db6e93e 100644
|
||||
--- a/output.c
|
||||
+++ b/output.c
|
||||
@@ -22,9 +22,10 @@ static int current_depth = 0;
|
||||
static int current_column = 0;
|
||||
|
||||
static void
|
||||
-output_indent(Process *proc) {
|
||||
- current_column +=
|
||||
- fprintf(options.output, "%*s", options.indent * proc->callstack_depth, "");
|
||||
+output_indent(struct Process *proc)
|
||||
+{
|
||||
+ int d = options.indent * (proc->callstack_depth - 1);
|
||||
+ current_column += fprintf(options.output, "%*s", d, "");
|
||||
}
|
||||
|
||||
static void
|
||||
diff --git a/proc.c b/proc.c
|
||||
index 51833fe..54afbe0 100644
|
||||
--- a/proc.c
|
||||
+++ b/proc.c
|
||||
@@ -49,6 +49,7 @@ arch_dynlink_done(struct Process *proc)
|
||||
#endif
|
||||
|
||||
static void add_process(struct Process *proc, int was_exec);
|
||||
+static void unlist_process(struct Process *proc);
|
||||
|
||||
static int
|
||||
process_bare_init(struct Process *proc, const char *filename,
|
||||
@@ -96,7 +97,7 @@ process_bare_destroy(struct Process *proc, int was_exec)
|
||||
dict_clear(proc->breakpoints);
|
||||
if (!was_exec) {
|
||||
free(proc->filename);
|
||||
- remove_process(proc);
|
||||
+ unlist_process(proc);
|
||||
}
|
||||
}
|
||||
|
||||
10240
ltrace-0.6.0-libs.patch
10240
ltrace-0.6.0-libs.patch
File diff suppressed because it is too large
Load Diff
@ -1,30 +0,0 @@
|
||||
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;
|
||||
}
|
||||
@ -1,162 +0,0 @@
|
||||
From fcf256ceeab4b0b74cf1e18122e894aafce94fdc Mon Sep 17 00:00:00 2001
|
||||
From: Petr Machata <pmachata@redhat.com>
|
||||
Date: Thu, 30 Aug 2012 01:37:23 +0200
|
||||
Subject: [PATCH] PPC64 passes floating point equivalent structures in
|
||||
registers as well
|
||||
|
||||
Extract the structure unpacking code from s390 back end into the generic
|
||||
type module. Call this from both s390 and ppc back ends.
|
||||
---
|
||||
sysdeps/linux-gnu/ppc/fetch.c | 21 +++++++++++++++++++--
|
||||
sysdeps/linux-gnu/s390/fetch.c | 31 +------------------------------
|
||||
type.c | 34 ++++++++++++++++++++++++++++++++++
|
||||
type.h | 7 +++++++
|
||||
4 files changed, 61 insertions(+), 32 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/linux-gnu/ppc/fetch.c b/sysdeps/linux-gnu/ppc/fetch.c
|
||||
index 44cd056..40c91d9 100644
|
||||
--- a/sysdeps/linux-gnu/ppc/fetch.c
|
||||
+++ b/sysdeps/linux-gnu/ppc/fetch.c
|
||||
@@ -340,13 +340,30 @@ allocate_argument(struct fetch_context *ctx, struct Process *proc,
|
||||
while (slots-- > 0) {
|
||||
struct value val;
|
||||
value_init(&val, proc, NULL, long_info, 0);
|
||||
- int rc = allocate_gpr(ctx, proc, long_info, &val);
|
||||
+
|
||||
+ /* Floating point registers [...] are used [...] to
|
||||
+ pass [...] one member aggregates passed by value
|
||||
+ containing a floating point value[.] Note that for
|
||||
+ one member aggregates, "containing" extends to
|
||||
+ aggregates within aggregates ad infinitum. */
|
||||
+ int rc;
|
||||
+ struct arg_type_info *fp_info
|
||||
+ = type_get_fp_equivalent(valuep->type);
|
||||
+ if (fp_info != NULL)
|
||||
+ rc = allocate_float(ctx, proc, fp_info, &val);
|
||||
+ else
|
||||
+ rc = allocate_gpr(ctx, proc, long_info, &val);
|
||||
+
|
||||
if (rc >= 0) {
|
||||
memcpy(ptr, value_get_data(&val, NULL), width);
|
||||
ptr += width;
|
||||
}
|
||||
value_destroy(&val);
|
||||
- if (rc < 0)
|
||||
+
|
||||
+ /* Bail out if we failed or if we are dealing with
|
||||
+ * FP-equivalent. Those don't need the adjustments
|
||||
+ * made below. */
|
||||
+ if (rc < 0 || fp_info != NULL)
|
||||
return rc;
|
||||
}
|
||||
|
||||
diff --git a/sysdeps/linux-gnu/s390/fetch.c b/sysdeps/linux-gnu/s390/fetch.c
|
||||
index 5d26b35..c46ef7c 100644
|
||||
--- a/sysdeps/linux-gnu/s390/fetch.c
|
||||
+++ b/sysdeps/linux-gnu/s390/fetch.c
|
||||
@@ -61,35 +61,6 @@ s390x(struct fetch_context *ctx)
|
||||
}
|
||||
|
||||
static int
|
||||
-fp_equivalent(struct arg_type_info *info)
|
||||
-{
|
||||
- switch (info->type) {
|
||||
- case ARGTYPE_VOID:
|
||||
- case ARGTYPE_INT:
|
||||
- case ARGTYPE_UINT:
|
||||
- case ARGTYPE_LONG:
|
||||
- case ARGTYPE_ULONG:
|
||||
- case ARGTYPE_CHAR:
|
||||
- case ARGTYPE_SHORT:
|
||||
- case ARGTYPE_USHORT:
|
||||
- case ARGTYPE_ARRAY:
|
||||
- case ARGTYPE_POINTER:
|
||||
- return 0;
|
||||
-
|
||||
- case ARGTYPE_FLOAT:
|
||||
- case ARGTYPE_DOUBLE:
|
||||
- return 1;
|
||||
-
|
||||
- case ARGTYPE_STRUCT:
|
||||
- if (type_struct_size(info) != 1)
|
||||
- return 0;
|
||||
- return fp_equivalent(type_element(info, 0));
|
||||
- }
|
||||
- assert(info->type != info->type);
|
||||
- abort();
|
||||
-}
|
||||
-
|
||||
-static int
|
||||
fetch_register_banks(struct Process *proc, struct fetch_context *ctx)
|
||||
{
|
||||
ptrace_area parea;
|
||||
@@ -256,7 +227,7 @@ arch_fetch_arg_next(struct fetch_context *ctx, enum tof type,
|
||||
return 0;
|
||||
|
||||
case ARGTYPE_STRUCT:
|
||||
- if (fp_equivalent(info))
|
||||
+ if (type_get_fp_equivalent(info) != NULL)
|
||||
/* fall through */
|
||||
case ARGTYPE_FLOAT:
|
||||
case ARGTYPE_DOUBLE:
|
||||
diff --git a/type.c b/type.c
|
||||
index 6341042..4b9a645 100644
|
||||
--- a/type.c
|
||||
+++ b/type.c
|
||||
@@ -513,3 +513,37 @@ type_is_signed(enum arg_type type)
|
||||
}
|
||||
abort();
|
||||
}
|
||||
+
|
||||
+struct arg_type_info *
|
||||
+type_get_fp_equivalent(struct arg_type_info *info)
|
||||
+{
|
||||
+ /* Extract innermost structure. Give up early if any
|
||||
+ * component has more than one element. */
|
||||
+ while (info->type == ARGTYPE_STRUCT) {
|
||||
+ if (type_struct_size(info) != 1)
|
||||
+ return NULL;
|
||||
+ info = type_element(info, 0);
|
||||
+ }
|
||||
+
|
||||
+ switch (info->type) {
|
||||
+ case ARGTYPE_CHAR:
|
||||
+ case ARGTYPE_SHORT:
|
||||
+ case ARGTYPE_INT:
|
||||
+ case ARGTYPE_LONG:
|
||||
+ case ARGTYPE_UINT:
|
||||
+ case ARGTYPE_ULONG:
|
||||
+ case ARGTYPE_USHORT:
|
||||
+ case ARGTYPE_VOID:
|
||||
+ case ARGTYPE_ARRAY:
|
||||
+ case ARGTYPE_POINTER:
|
||||
+ return NULL;
|
||||
+
|
||||
+ case ARGTYPE_FLOAT:
|
||||
+ case ARGTYPE_DOUBLE:
|
||||
+ return info;
|
||||
+
|
||||
+ case ARGTYPE_STRUCT:
|
||||
+ abort();
|
||||
+ }
|
||||
+ abort();
|
||||
+}
|
||||
diff --git a/type.h b/type.h
|
||||
index 545173c..53123b8 100644
|
||||
--- a/type.h
|
||||
+++ b/type.h
|
||||
@@ -130,4 +130,11 @@ int type_is_integral(enum arg_type type);
|
||||
/* Whether TYPE, which shall be integral, is a signed type. */
|
||||
int type_is_signed(enum arg_type type);
|
||||
|
||||
+/* If INFO is floating point equivalent type, return the corresponding
|
||||
+ * floating point type. Otherwise return NULL. Floating point
|
||||
+ * equivalent types are either ARGTYPE_FLOAT, or ARGTYPE_DOUBLE, or
|
||||
+ * ARGTYPE_STRUCT whose sole member is a floating point equivalent
|
||||
+ * type. */
|
||||
+struct arg_type_info *type_get_fp_equivalent(struct arg_type_info *info);
|
||||
+
|
||||
#endif /* TYPE_H */
|
||||
--
|
||||
1.7.6.5
|
||||
|
||||
@ -1,373 +0,0 @@
|
||||
diff --git a/sysdeps/linux-gnu/ppc/arch.h b/sysdeps/linux-gnu/ppc/arch.h
|
||||
index 711b4a3..64c1821 100644
|
||||
--- a/sysdeps/linux-gnu/ppc/arch.h
|
||||
+++ b/sysdeps/linux-gnu/ppc/arch.h
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
/* Start of arch-specific functions. */
|
||||
#define ARCH_ENDIAN_BIG
|
||||
+#define ARCH_HAVE_ATOMIC_SINGLESTEP
|
||||
|
||||
#define PPC_NOP { 0x60, 0x00, 0x00, 0x00 }
|
||||
#define PPC_NOP_LENGTH 4
|
||||
diff --git a/sysdeps/linux-gnu/ppc/trace.c b/sysdeps/linux-gnu/ppc/trace.c
|
||||
index 8642157..05993de 100644
|
||||
--- a/sysdeps/linux-gnu/ppc/trace.c
|
||||
+++ b/sysdeps/linux-gnu/ppc/trace.c
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "ptrace.h"
|
||||
+#include "breakpoint.h"
|
||||
|
||||
#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
|
||||
# define PTRACE_PEEKUSER PTRACE_PEEKUSR
|
||||
@@ -197,3 +197,85 @@ arch_umovelong (Process *proc, void *addr, long *result, arg_type_info *info) {
|
||||
memcpy(&arch->regs_copy, &arch->regs, sizeof(arch->regs));
|
||||
memcpy(&arch->fpregs_copy, &arch->fpregs, sizeof(arch->fpregs));
|
||||
}
|
||||
+
|
||||
+/* The atomic skip code is mostly taken from GDB. */
|
||||
+
|
||||
+/* Instruction masks used during single-stepping of atomic
|
||||
+ * sequences. This was lifted from GDB. */
|
||||
+#define LWARX_MASK 0xfc0007fe
|
||||
+#define LWARX_INSTRUCTION 0x7c000028
|
||||
+#define LDARX_INSTRUCTION 0x7c0000A8
|
||||
+#define STWCX_MASK 0xfc0007ff
|
||||
+#define STWCX_INSTRUCTION 0x7c00012d
|
||||
+#define STDCX_INSTRUCTION 0x7c0001ad
|
||||
+#define BC_MASK 0xfc000000
|
||||
+#define BC_INSTRUCTION 0x40000000
|
||||
+
|
||||
+int
|
||||
+arch_atomic_singlestep(struct Process *proc, struct breakpoint *sbp,
|
||||
+ int (*add_cb)(void *addr, void *data),
|
||||
+ void *add_cb_data)
|
||||
+{
|
||||
+ void *addr = sbp->addr;
|
||||
+ debug(1, "pid=%d addr=%p", proc->pid, addr);
|
||||
+
|
||||
+ /* If the original instruction was lwarx/ldarx, we can't
|
||||
+ * single-step over it, instead we have to execute the whole
|
||||
+ * atomic block at once. */
|
||||
+ union {
|
||||
+ uint32_t insn;
|
||||
+ char buf[4];
|
||||
+ } u;
|
||||
+ memcpy(u.buf, sbp->orig_value, BREAKPOINT_LENGTH);
|
||||
+
|
||||
+ if ((u.insn & LWARX_MASK) != LWARX_INSTRUCTION
|
||||
+ && (u.insn & LWARX_MASK) != LDARX_INSTRUCTION)
|
||||
+ return 1;
|
||||
+
|
||||
+ int insn_count;
|
||||
+ for (insn_count = 0; ; ++insn_count) {
|
||||
+ addr += 4;
|
||||
+ unsigned long l = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0);
|
||||
+ if (l == (unsigned long)-1 && errno)
|
||||
+ return -1;
|
||||
+ uint32_t insn;
|
||||
+#ifdef __powerpc64__
|
||||
+ insn = l >> 32;
|
||||
+#else
|
||||
+ insn = l;
|
||||
+#endif
|
||||
+
|
||||
+ /* If we hit a branch instruction, give up. The
|
||||
+ * computation could escape that way and we'd have to
|
||||
+ * treat that case specially. */
|
||||
+ if ((insn & BC_MASK) == BC_INSTRUCTION) {
|
||||
+ debug(1, "pid=%d, found branch at %p, giving up",
|
||||
+ proc->pid, addr);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if ((insn & STWCX_MASK) == STWCX_INSTRUCTION
|
||||
+ || (insn & STWCX_MASK) == STDCX_INSTRUCTION) {
|
||||
+ debug(1, "pid=%d, found end of atomic block at %p",
|
||||
+ proc->pid, addr);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* Arbitrary cut-off. If we didn't find the
|
||||
+ * terminating instruction by now, just give up. */
|
||||
+ if (insn_count > 16) {
|
||||
+ debug(1, "pid=%d, couldn't find end of atomic block",
|
||||
+ proc->pid);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Put the breakpoint to the next instruction. */
|
||||
+ addr += 4;
|
||||
+ if (add_cb(addr, add_cb_data) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ debug(1, "PTRACE_CONT");
|
||||
+ ptrace(PTRACE_CONT, proc->pid, 0, 0);
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c
|
||||
index 9ecea1e..d962048 100644
|
||||
--- a/sysdeps/linux-gnu/trace.c
|
||||
+++ b/sysdeps/linux-gnu/trace.c
|
||||
@@ -249,6 +249,9 @@ struct process_stopping_handler
|
||||
/* The pointer being re-enabled. */
|
||||
struct breakpoint *breakpoint_being_enabled;
|
||||
|
||||
+ /* Artificial atomic skip breakpoint, if any needed. */
|
||||
+ void *atomic_skip_bp_addr;
|
||||
+
|
||||
enum {
|
||||
/* We are waiting for everyone to land in t/T. */
|
||||
psh_stopping = 0,
|
||||
@@ -612,12 +615,84 @@ all_stops_accountable(struct pid_set * pids)
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static void
|
||||
-singlestep(Process * proc)
|
||||
+/* The protocol is: 0 for success, negative for failure, positive if
|
||||
+ * default singlestep is to be used. */
|
||||
+int arch_atomic_singlestep(struct Process *proc, struct breakpoint *sbp,
|
||||
+ int (*add_cb)(void *addr, void *data),
|
||||
+ void *add_cb_data);
|
||||
+
|
||||
+#ifndef ARCH_HAVE_ATOMIC_SINGLESTEP
|
||||
+int
|
||||
+arch_atomic_singlestep(struct Process *proc, struct breakpoint *sbp,
|
||||
+ int (*add_cb)(void *addr, void *data),
|
||||
+ void *add_cb_data)
|
||||
+{
|
||||
+ return 1;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static int
|
||||
+atomic_singlestep_add_bp(void *addr, void *data)
|
||||
+{
|
||||
+ struct process_stopping_handler *self = data;
|
||||
+ struct Process *proc = self->task_enabling_breakpoint;
|
||||
+
|
||||
+ /* Only support single address as of now. */
|
||||
+ assert(self->atomic_skip_bp_addr == NULL);
|
||||
+
|
||||
+ self->atomic_skip_bp_addr = addr + 4;
|
||||
+ insert_breakpoint(proc->leader, self->atomic_skip_bp_addr, NULL, 1);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+singlestep(struct process_stopping_handler *self)
|
||||
{
|
||||
+ struct Process *proc = self->task_enabling_breakpoint;
|
||||
+
|
||||
+ int status = arch_atomic_singlestep(self->task_enabling_breakpoint,
|
||||
+ self->breakpoint_being_enabled,
|
||||
+ &atomic_singlestep_add_bp, self);
|
||||
+
|
||||
+ /* Propagate failure and success. */
|
||||
+ if (status <= 0)
|
||||
+ return status;
|
||||
+
|
||||
+ /* Otherwise do the default action: singlestep. */
|
||||
debug(1, "PTRACE_SINGLESTEP");
|
||||
- if (ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0))
|
||||
+ if (ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0)) {
|
||||
perror("PTRACE_SINGLESTEP");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+post_singlestep(struct process_stopping_handler *self, Event **eventp)
|
||||
+{
|
||||
+ continue_for_sigstop_delivery(&self->pids);
|
||||
+
|
||||
+ if ((*eventp)->type == EVENT_BREAKPOINT)
|
||||
+ *eventp = NULL; // handled
|
||||
+
|
||||
+ if (self->atomic_skip_bp_addr != 0)
|
||||
+ delete_breakpoint(self->task_enabling_breakpoint->leader,
|
||||
+ self->atomic_skip_bp_addr);
|
||||
+
|
||||
+ self->breakpoint_being_enabled = NULL;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+singlestep_error(struct process_stopping_handler *self, Event **eventp)
|
||||
+{
|
||||
+ struct Process *teb = self->task_enabling_breakpoint;
|
||||
+ struct breakpoint *sbp = self->breakpoint_being_enabled;
|
||||
+ fprintf(stderr, "%d couldn't singlestep over %s (%p)\n",
|
||||
+ teb->pid, sbp->libsym != NULL ? sbp->libsym->name : NULL,
|
||||
+ sbp->addr);
|
||||
+ delete_breakpoint(teb->leader, sbp->addr);
|
||||
+ post_singlestep(self, eventp);
|
||||
}
|
||||
|
||||
/* This event handler is installed when we are in the process of
|
||||
@@ -670,7 +745,11 @@ process_stopping_on_event(Event_Handler * super, Event * event)
|
||||
teb->pid);
|
||||
if (sbp->enabled)
|
||||
disable_breakpoint(teb, sbp);
|
||||
- singlestep(teb);
|
||||
+ if (singlestep(self) < 0) {
|
||||
+ singlestep_error(self, &event);
|
||||
+ goto psh_sinking;
|
||||
+ }
|
||||
+
|
||||
self->state = state = psh_singlestep;
|
||||
}
|
||||
break;
|
||||
@@ -682,7 +761,10 @@ process_stopping_on_event(Event_Handler * super, Event * event)
|
||||
|
||||
/* This is not the singlestep that we are waiting for. */
|
||||
if (event->type == EVENT_SIGNAL) {
|
||||
- singlestep(task);
|
||||
+ if (singlestep(self) < 0) {
|
||||
+ singlestep_error(self, &event);
|
||||
+ goto psh_sinking;
|
||||
+ }
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -692,18 +774,13 @@ process_stopping_on_event(Event_Handler * super, Event * event)
|
||||
if (sbp->enabled)
|
||||
enable_breakpoint(teb, sbp);
|
||||
|
||||
- continue_for_sigstop_delivery(&self->pids);
|
||||
-
|
||||
- self->breakpoint_being_enabled = NULL;
|
||||
- self->state = state = psh_sinking;
|
||||
-
|
||||
- if (event->type == EVENT_BREAKPOINT)
|
||||
- event = NULL; // handled
|
||||
- } else
|
||||
- break;
|
||||
-
|
||||
- /* fall-through */
|
||||
+ post_singlestep(self, &event);
|
||||
+ goto psh_sinking;
|
||||
+ }
|
||||
+ break;
|
||||
|
||||
+ psh_sinking:
|
||||
+ state = self->state = psh_sinking;
|
||||
case psh_sinking:
|
||||
if (await_sigstop_delivery(&self->pids, task_info, event))
|
||||
process_stopping_done(self, leader);
|
||||
diff --git a/testsuite/ltrace.torture/ppc-lwarx.c b/testsuite/ltrace.torture/ppc-lwarx.c
|
||||
new file mode 100644
|
||||
index 0000000..0716407
|
||||
--- /dev/null
|
||||
+++ b/testsuite/ltrace.torture/ppc-lwarx.c
|
||||
@@ -0,0 +1,44 @@
|
||||
+/*
|
||||
+ * This file is part of ltrace.
|
||||
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 2 of the
|
||||
+ * License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful, but
|
||||
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, write to the Free Software
|
||||
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
+ * 02110-1301 USA
|
||||
+ */
|
||||
+
|
||||
+#include <stdint.h>
|
||||
+
|
||||
+__attribute__((noinline, optimize(3))) void
|
||||
+atomic_add(uint32_t *a, uint32_t b)
|
||||
+{
|
||||
+ __asm__ volatile("lwarx 9,0,%0\n"
|
||||
+ "add 9,9,%2\n"
|
||||
+ "stwcx. 9,0,%0\n"
|
||||
+ "bne- atomic_add\n"
|
||||
+ : "=r"(a)
|
||||
+ : "0"(a), "r"(b)
|
||||
+ : "%r9");
|
||||
+}
|
||||
+
|
||||
+uint32_t a = 0;
|
||||
+
|
||||
+__attribute__((optimize(0))) int
|
||||
+main(int argc, char **argv)
|
||||
+{
|
||||
+ atomic_add(&a, 5);
|
||||
+ atomic_add(&a, 10);
|
||||
+ atomic_add(&a, 15);
|
||||
+ return a;
|
||||
+}
|
||||
diff --git a/testsuite/ltrace.torture/ppc-lwarx.exp b/testsuite/ltrace.torture/ppc-lwarx.exp
|
||||
new file mode 100644
|
||||
index 0000000..bc2eba4
|
||||
--- /dev/null
|
||||
+++ b/testsuite/ltrace.torture/ppc-lwarx.exp
|
||||
@@ -0,0 +1,55 @@
|
||||
+# This file is part of ltrace.
|
||||
+# Copyright (C) 2012 Petr Machata, Red Hat Inc.
|
||||
+#
|
||||
+# This program is free software; you can redistribute it and/or
|
||||
+# modify it under the terms of the GNU General Public License as
|
||||
+# published by the Free Software Foundation; either version 2 of the
|
||||
+# License, or (at your option) any later version.
|
||||
+#
|
||||
+# This program is distributed in the hope that it will be useful, but
|
||||
+# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+# General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program; if not, write to the Free Software
|
||||
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
+# 02110-1301 USA
|
||||
+
|
||||
+set testfile "ppc-lwarx"
|
||||
+set srcfile ${testfile}.c
|
||||
+set binfile ${testfile}
|
||||
+
|
||||
+if [get_compiler_info $binfile] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+if { [istarget powerpc*-*] } then {
|
||||
+ 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 "-x" "atomic_add" "-e" "!atoi"
|
||||
+
|
||||
+ # 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
|
||||
+ }
|
||||
+
|
||||
+ set pattern "atomic_add(.*, 5,.*)"
|
||||
+ ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
|
||||
+ set pattern "atomic_add(.*, 10,.*)"
|
||||
+ ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
|
||||
+ set pattern "atomic_add(.*, 15,.*)"
|
||||
+ ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
|
||||
+}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,16 +0,0 @@
|
||||
diff -up ltrace-0.6.0/output.c\~ ltrace-0.6.0/output.c
|
||||
--- ltrace-0.6.0/output.c~ 2011-02-14 16:48:25.000000000 +0100
|
||||
+++ ltrace-0.6.0/output.c 2011-02-15 00:35:39.000000000 +0100
|
||||
@@ -202,7 +204,9 @@ output_left(enum tof type, Process *proc
|
||||
current_column += fprintf(options.output, ", ");
|
||||
}
|
||||
}
|
||||
- if (func->params_right) {
|
||||
+ if (func->params_right
|
||||
+ || func->return_info->type == ARGTYPE_STRING_N
|
||||
+ || func->return_info->type == ARGTYPE_ARRAY) {
|
||||
save_register_args(type, proc);
|
||||
}
|
||||
}
|
||||
|
||||
Diff finished. Tue Feb 15 00:35:44 2011
|
||||
@ -1,212 +0,0 @@
|
||||
From cec06ec8282c538a40bde968ae36fe8356daffaa Mon Sep 17 00:00:00 2001
|
||||
From: Petr Machata <pmachata@redhat.com>
|
||||
Date: Tue, 10 Apr 2012 13:31:55 +0200
|
||||
Subject: [PATCH] Warn when we fail to trace and SELinux boolean deny_ptrace
|
||||
is in effect
|
||||
|
||||
---
|
||||
ChangeLog | 7 ++++++
|
||||
common.h | 4 +++
|
||||
configure.ac | 5 ++++
|
||||
proc.c | 1 +
|
||||
sysdeps/linux-gnu/trace.c | 51 ++++++++++++++++++++++++++++++++++++--------
|
||||
5 files changed, 58 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/common.h b/common.h
|
||||
index fa80076..2399e29 100644
|
||||
--- a/common.h
|
||||
+++ b/common.h
|
||||
@@ -359,2 +359,6 @@ extern int linkmap_init(Process *, struct ltelf *);
|
||||
|
||||
+/* Called when trace_me or primary trace_pid fail. This may plug in
|
||||
+ * any platform-specific knowledge of why it could be so. */
|
||||
+void trace_fail_warning(pid_t pid);
|
||||
+
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 7fcfda5..42d6158 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -82,6 +82,11 @@ AC_CHECK_LIB([supc++], [__cxa_demangle], [
|
||||
AC_SUBST(libsupcxx_LIBS)
|
||||
|
||||
|
||||
+dnl Check security_get_boolean_active availability.
|
||||
+AC_CHECK_HEADERS(selinux/selinux.h)
|
||||
+AC_CHECK_LIB(selinux, security_get_boolean_active)
|
||||
+
|
||||
+
|
||||
# HAVE_LIBUNWIND
|
||||
AC_ARG_WITH(libunwind,
|
||||
AS_HELP_STRING([--with-libunwind], [Use libunwind frame unwinding support]),
|
||||
diff -up ltrace-0.6.0/configure\~ ltrace-0.6.0/configure
|
||||
--- ltrace-0.6.0/configure~ 2012-04-11 12:56:00.688263027 +0200
|
||||
+++ ltrace-0.6.0/configure 2012-04-11 12:55:49.787935890 +0200
|
||||
@@ -11029,6 +11689,65 @@ fi
|
||||
|
||||
|
||||
|
||||
+for ac_header in selinux/selinux.h
|
||||
+do :
|
||||
+ ac_fn_c_check_header_mongrel "$LINENO" "selinux/selinux.h" "ac_cv_header_selinux_selinux_h" "$ac_includes_default"
|
||||
+if test "x$ac_cv_header_selinux_selinux_h" = xyes; then :
|
||||
+ cat >>confdefs.h <<_ACEOF
|
||||
+#define HAVE_SELINUX_SELINUX_H 1
|
||||
+_ACEOF
|
||||
+
|
||||
+fi
|
||||
+
|
||||
+done
|
||||
+
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for security_get_boolean_active in -lselinux" >&5
|
||||
+$as_echo_n "checking for security_get_boolean_active in -lselinux... " >&6; }
|
||||
+if ${ac_cv_lib_selinux_security_get_boolean_active+:} false; then :
|
||||
+ $as_echo_n "(cached) " >&6
|
||||
+else
|
||||
+ ac_check_lib_save_LIBS=$LIBS
|
||||
+LIBS="-lselinux $LIBS"
|
||||
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+
|
||||
+/* Override any GCC internal prototype to avoid an error.
|
||||
+ Use char because int might match the return type of a GCC
|
||||
+ builtin and then its argument prototype would still apply. */
|
||||
+#ifdef __cplusplus
|
||||
+extern "C"
|
||||
+#endif
|
||||
+char security_get_boolean_active ();
|
||||
+int
|
||||
+main ()
|
||||
+{
|
||||
+return security_get_boolean_active ();
|
||||
+ ;
|
||||
+ return 0;
|
||||
+}
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_link "$LINENO"; then :
|
||||
+ ac_cv_lib_selinux_security_get_boolean_active=yes
|
||||
+else
|
||||
+ ac_cv_lib_selinux_security_get_boolean_active=no
|
||||
+fi
|
||||
+rm -f core conftest.err conftest.$ac_objext \
|
||||
+ conftest$ac_exeext conftest.$ac_ext
|
||||
+LIBS=$ac_check_lib_save_LIBS
|
||||
+fi
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_selinux_security_get_boolean_active" >&5
|
||||
+$as_echo "$ac_cv_lib_selinux_security_get_boolean_active" >&6; }
|
||||
+if test "x$ac_cv_lib_selinux_security_get_boolean_active" = xyes; then :
|
||||
+ cat >>confdefs.h <<_ACEOF
|
||||
+#define HAVE_LIBSELINUX 1
|
||||
+_ACEOF
|
||||
+
|
||||
+ LIBS="-lselinux $LIBS"
|
||||
+
|
||||
+fi
|
||||
+
|
||||
+
|
||||
+
|
||||
# HAVE_LIBUNWIND
|
||||
|
||||
# Check whether --with-libunwind was given.
|
||||
diff --git a/proc.c b/proc.c
|
||||
index 106b6a0..ded0c95 100644
|
||||
--- a/proc.c
|
||||
+++ b/proc.c
|
||||
@@ -94,6 +94,7 @@ open_pid(pid_t pid)
|
||||
if (open_one_pid(pid)) {
|
||||
fprintf(stderr, "Cannot attach to pid %u: %s\n",
|
||||
pid, strerror(errno));
|
||||
+ trace_fail_warning(pid);
|
||||
return;
|
||||
}
|
||||
|
||||
diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c
|
||||
index 67e1f93..82a4154 100644
|
||||
--- a/sysdeps/linux-gnu/trace.c
|
||||
+++ b/sysdeps/linux-gnu/trace.c
|
||||
@@ -10,2 +10,7 @@
|
||||
|
||||
+#include "config.h"
|
||||
+#ifdef HAVE_LIBSELINUX
|
||||
+# include <selinux/selinux.h>
|
||||
+#endif
|
||||
+
|
||||
/* If the system headers did not provide the constants, hard-code the normal
|
||||
@@ -69,10 +75,32 @@ umovelong (Process *proc, void *addr, long *result, arg_type_info *info) {
|
||||
#endif
|
||||
|
||||
void
|
||||
-trace_me(void) {
|
||||
+trace_fail_warning(pid_t pid)
|
||||
+{
|
||||
+ /* This was adapted from GDB. */
|
||||
+#ifdef HAVE_LIBSELINUX
|
||||
+ static int checked = 0;
|
||||
+ if (checked)
|
||||
+ return;
|
||||
+ checked = 1;
|
||||
+
|
||||
+ /* -1 is returned for errors, 0 if it has no effect, 1 if
|
||||
+ * PTRACE_ATTACH is forbidden. */
|
||||
+ if (security_get_boolean_active("deny_ptrace") == 1)
|
||||
+ fprintf(stderr,
|
||||
+"The SELinux boolean 'deny_ptrace' is enabled, which may prevent ltrace from\n"
|
||||
+"tracing other processes. You can disable this process attach protection by\n"
|
||||
+"issuing 'setsebool deny_ptrace=0' in the superuser context.\n");
|
||||
+#endif /* HAVE_LIBSELINUX */
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+trace_me(void)
|
||||
+{
|
||||
debug(DEBUG_PROCESS, "trace_me: pid=%d", getpid());
|
||||
if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
|
||||
perror("PTRACE_TRACEME");
|
||||
+ trace_fail_warning(getpid());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -101,11 +129,14 @@ I'll now try to proceed with tracing, but this shouldn't be happening.\n");
|
||||
}
|
||||
|
||||
int
|
||||
-trace_pid(pid_t pid) {
|
||||
+trace_pid(pid_t pid)
|
||||
+{
|
||||
debug(DEBUG_PROCESS, "trace_pid: pid=%d", pid);
|
||||
- if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) {
|
||||
+ /* This shouldn't emit error messages, as there are legitimate
|
||||
+ * reasons that the PID can't be attached: like it may have
|
||||
+ * already ended. */
|
||||
+ if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0)
|
||||
return -1;
|
||||
- }
|
||||
|
||||
/* man ptrace: PTRACE_ATTACH attaches to the process specified
|
||||
in pid. The child is sent a SIGSTOP, but will not
|
||||
--
|
||||
1.7.7.6
|
||||
|
||||
diff -up ./config.h.in~ ./config.h.in
|
||||
--- ./config.h.in~ 2011-02-14 17:01:18.000000000 +0100
|
||||
+++ ./config.h.in 2012-04-11 13:19:10.000000000 +0200
|
||||
@@ -45,6 +45,9 @@
|
||||
/* we have libiberty */
|
||||
#undef HAVE_LIBIBERTY
|
||||
|
||||
+/* Define to 1 if you have the `selinux' library (-lselinux). */
|
||||
+#undef HAVE_LIBSELINUX
|
||||
+
|
||||
/* we have libsupc++ */
|
||||
#undef HAVE_LIBSUPC__
|
||||
|
||||
@@ -72,6 +75,9 @@
|
||||
/* Define to 1 if you have the `rmdir' function. */
|
||||
#undef HAVE_RMDIR
|
||||
|
||||
+/* Define to 1 if you have the <selinux/selinux.h> header file. */
|
||||
+#undef HAVE_SELINUX_SELINUX_H
|
||||
+
|
||||
/* Define to 1 if you have the <stddef.h> header file. */
|
||||
#undef HAVE_STDDEF_H
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
From 6aa01523f249f9763ccd71db9f46969a6e5d8cfd Mon Sep 17 00:00:00 2001
|
||||
From: Paul Buerger <pbuerger@avetec.org>
|
||||
Date: Wed, 12 Sep 2012 10:58:52 -0400
|
||||
Subject: [PATCH] reported time in system call was too large
|
||||
|
||||
when -S and -T are specified and if the system call spans
|
||||
a second boundary, the reported time in the system call
|
||||
was too large by precisely 2 seconds
|
||||
|
||||
Signed-off-by: Paul Buerger <pbuerger@avetec.org>
|
||||
---
|
||||
handle_event.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/handle_event.c b/handle_event.c
|
||||
index 1720cb3..384e868 100644
|
||||
--- a/handle_event.c
|
||||
+++ b/handle_event.c
|
||||
@@ -522,7 +522,7 @@ calc_time_spent(Process *proc) {
|
||||
if (tv.tv_usec >= elem->time_spent.tv_usec) {
|
||||
diff.tv_usec = tv.tv_usec - elem->time_spent.tv_usec;
|
||||
} else {
|
||||
- diff.tv_sec++;
|
||||
+ diff.tv_sec--;
|
||||
diff.tv_usec = 1000000 + tv.tv_usec - elem->time_spent.tv_usec;
|
||||
}
|
||||
current_time_spent = diff;
|
||||
--
|
||||
1.7.6.5
|
||||
|
||||
@ -1,256 +0,0 @@
|
||||
diff --git a/handle_event.c b/handle_event.c
|
||||
index 725f50d..8c3c7ce 100644
|
||||
--- a/handle_event.c
|
||||
+++ b/handle_event.c
|
||||
@@ -565,11 +565,21 @@ void *get_count_register (Process *proc);
|
||||
}
|
||||
|
||||
static void
|
||||
+output_right_tos(struct Process *proc)
|
||||
+{
|
||||
+ size_t d = proc->callstack_depth;
|
||||
+ struct callstack_element *elem = &proc->callstack[d - 1];
|
||||
+ if (proc->state != STATE_IGNORED)
|
||||
+ output_right(LT_TOF_FUNCTIONR, proc, elem->c_un.libfunc->name);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
handle_breakpoint(Event *event)
|
||||
{
|
||||
int i, j;
|
||||
struct breakpoint *sbp;
|
||||
Process *leader = event->proc->leader;
|
||||
+ void *brk_addr = event->e_un.brk_addr;
|
||||
|
||||
/* The leader has terminated. */
|
||||
if (leader == NULL) {
|
||||
@@ -577,12 +587,14 @@ handle_breakpoint(Event *event)
|
||||
return;
|
||||
}
|
||||
|
||||
- debug(DEBUG_FUNCTION, "handle_breakpoint(pid=%d, addr=%p)", event->proc->pid, event->e_un.brk_addr);
|
||||
- debug(2, "event: breakpoint (%p)", event->e_un.brk_addr);
|
||||
+ debug(DEBUG_FUNCTION, "handle_breakpoint(pid=%d, addr=%p)",
|
||||
+ event->proc->pid, brk_addr);
|
||||
+ debug(2, "event: breakpoint (%p)", brk_addr);
|
||||
|
||||
for (i = event->proc->callstack_depth - 1; i >= 0; i--) {
|
||||
- if (event->e_un.brk_addr ==
|
||||
- event->proc->callstack[i].return_addr) {
|
||||
+ if (brk_addr == event->proc->callstack[i].return_addr) {
|
||||
+ struct library_symbol *libsym =
|
||||
+ event->proc->callstack[i].c_un.libfunc;
|
||||
#ifdef __powerpc__
|
||||
/*
|
||||
* PPC HACK! (XXX FIXME TODO)
|
||||
@@ -623,8 +625,6 @@ handle_breakpoint(Event *event)
|
||||
* so be sure to re-enable the breakpoint.
|
||||
*/
|
||||
unsigned long a;
|
||||
- struct library_symbol *libsym =
|
||||
- event->proc->callstack[i].c_un.libfunc;
|
||||
void *addr = sym2addr(event->proc, libsym);
|
||||
|
||||
if (libsym->plt_type != LS_TOPLT_POINT) {
|
||||
@@ -668,19 +679,37 @@ handle_breakpoint(Event *event)
|
||||
calc_time_spent(event->proc);
|
||||
}
|
||||
}
|
||||
- event->proc->return_addr = event->e_un.brk_addr;
|
||||
- if (event->proc->state != STATE_IGNORED) {
|
||||
- output_right(LT_TOF_FUNCTIONR, event->proc,
|
||||
- event->proc->callstack[i].c_un.libfunc->name);
|
||||
- }
|
||||
+ event->proc->return_addr = brk_addr;
|
||||
+
|
||||
+ output_right_tos(event->proc);
|
||||
callstack_pop(event->proc);
|
||||
- sbp = address2bpstruct(leader, event->e_un.brk_addr);
|
||||
+
|
||||
+ /* Pop also any other entries that seem like
|
||||
+ * they are linked to the current one: they
|
||||
+ * have the same return address, but were made
|
||||
+ * for different symbols. This should only
|
||||
+ * happen for entry point tracing, i.e. for -x
|
||||
+ * everywhere, or -x and -e on PPC64. */
|
||||
+ while (event->proc->callstack_depth > 0) {
|
||||
+ struct callstack_element *prev;
|
||||
+ size_t d = event->proc->callstack_depth;
|
||||
+ prev = &event->proc->callstack[d - 1];
|
||||
+
|
||||
+ if (prev->c_un.libfunc == libsym
|
||||
+ || prev->return_addr != brk_addr)
|
||||
+ break;
|
||||
+
|
||||
+ output_right_tos(event->proc);
|
||||
+ callstack_pop(event->proc);
|
||||
+ }
|
||||
+
|
||||
+ sbp = address2bpstruct(leader, brk_addr);
|
||||
continue_after_breakpoint(event->proc, sbp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
- if ((sbp = address2bpstruct(leader, event->e_un.brk_addr))) {
|
||||
+ if ((sbp = address2bpstruct(leader, brk_addr))) {
|
||||
breakpoint_on_hit(sbp, event->proc);
|
||||
|
||||
if (sbp->libsym == NULL) {
|
||||
@@ -711,7 +740,7 @@ handle_breakpoint(Event *event)
|
||||
|
||||
if (event->proc->state != STATE_IGNORED && !options.no_plt) {
|
||||
output_line(event->proc, "unexpected breakpoint at %p",
|
||||
- (void *)event->e_un.brk_addr);
|
||||
+ brk_addr);
|
||||
}
|
||||
continue_process(event->proc->pid);
|
||||
}
|
||||
@@ -742,7 +771,7 @@ callstack_push_syscall(Process *proc, int sysnum) {
|
||||
|
||||
static void
|
||||
callstack_push_symfunc(Process *proc, struct library_symbol *sym) {
|
||||
- struct callstack_element *elem, *prev;
|
||||
+ struct callstack_element *elem;
|
||||
|
||||
debug(DEBUG_FUNCTION, "callstack_push_symfunc(pid=%d, symbol=%s)", proc->pid, sym->name);
|
||||
/* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */
|
||||
@@ -752,8 +781,7 @@ callstack_push_symfunc(Process *proc, struct library_symbol *sym) {
|
||||
return;
|
||||
}
|
||||
|
||||
- prev = &proc->callstack[proc->callstack_depth-1];
|
||||
- elem = &proc->callstack[proc->callstack_depth];
|
||||
+ elem = &proc->callstack[proc->callstack_depth++];
|
||||
elem->is_syscall = 0;
|
||||
elem->c_un.libfunc = sym;
|
||||
|
||||
@@ -763,8 +791,6 @@ callstack_push_symfunc(Process *proc, struct library_symbol *sym) {
|
||||
}
|
||||
|
||||
/* handle functions like atexit() on mips which have no return */
|
||||
- if (elem->return_addr != prev->return_addr)
|
||||
- proc->callstack_depth++;
|
||||
if (opt_T || options.summary) {
|
||||
struct timezone tz;
|
||||
gettimeofday(&elem->time_spent, &tz);
|
||||
diff --git a/testsuite/ltrace.main/branch_func.c b/testsuite/ltrace.main/branch_func.c
|
||||
new file mode 100644
|
||||
index 0000000..0ce311d
|
||||
--- /dev/null
|
||||
+++ b/testsuite/ltrace.main/branch_func.c
|
||||
@@ -0,0 +1,51 @@
|
||||
+/*
|
||||
+ * This file is part of ltrace.
|
||||
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 2 of the
|
||||
+ * License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful, but
|
||||
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, write to the Free Software
|
||||
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
+ * 02110-1301 USA
|
||||
+ */
|
||||
+
|
||||
+/* This is specially made to produce tail calls. We then trace them
|
||||
+ * and see if ltrace handles it well, or whether its internal stack
|
||||
+ * overflows. */
|
||||
+
|
||||
+__attribute__((noinline, optimize(3))) int
|
||||
+func3(int i)
|
||||
+{
|
||||
+ return i + 1;
|
||||
+}
|
||||
+
|
||||
+__attribute__((noinline, optimize(3))) int
|
||||
+func2(int i)
|
||||
+{
|
||||
+ return func3(i * 3);
|
||||
+}
|
||||
+
|
||||
+__attribute__((noinline, optimize(3))) int
|
||||
+func1(int i)
|
||||
+{
|
||||
+ return func2(i + 2);
|
||||
+}
|
||||
+
|
||||
+__attribute__((optimize(0))) int
|
||||
+main(int argc, char **argv)
|
||||
+{
|
||||
+ int counter = 0;
|
||||
+ int i;
|
||||
+ for (i = 0; i < 100; ++i)
|
||||
+ counter += func1(i);
|
||||
+ return counter;
|
||||
+}
|
||||
diff --git a/testsuite/ltrace.main/branch_func.exp b/testsuite/ltrace.main/branch_func.exp
|
||||
new file mode 100644
|
||||
index 0000000..fec5700
|
||||
--- /dev/null
|
||||
+++ b/testsuite/ltrace.main/branch_func.exp
|
||||
@@ -0,0 +1,57 @@
|
||||
+# This file is part of ltrace.
|
||||
+# Copyright (C) 2012 Petr Machata, Red Hat Inc.
|
||||
+#
|
||||
+# This program is free software; you can redistribute it and/or
|
||||
+# modify it under the terms of the GNU General Public License as
|
||||
+# published by the Free Software Foundation; either version 2 of the
|
||||
+# License, or (at your option) any later version.
|
||||
+#
|
||||
+# This program is distributed in the hope that it will be useful, but
|
||||
+# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+# General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program; if not, write to the Free Software
|
||||
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
+# 02110-1301 USA
|
||||
+
|
||||
+set testfile "branch_func"
|
||||
+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 "-x" "func1" "-x" "func2" "-x" "func3"
|
||||
+
|
||||
+# 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
|
||||
+}
|
||||
+
|
||||
+set pattern "func1(.*unfinished"
|
||||
+ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 100
|
||||
+set pattern "func2(.*unfinished"
|
||||
+ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 100
|
||||
+set pattern "func3(.*)"
|
||||
+ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 100
|
||||
+set pattern "func2.resumed"
|
||||
+ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 100
|
||||
+set pattern "func1.resumed"
|
||||
+ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 100
|
||||
@ -1,406 +0,0 @@
|
||||
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
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,88 +0,0 @@
|
||||
From 78ed40f161c102a10c6033c28ad9a80e5ffe9550 Mon Sep 17 00:00:00 2001
|
||||
From: Petr Machata <pmachata@redhat.com>
|
||||
Date: Sat, 22 Sep 2012 18:19:24 +0200
|
||||
Subject: [PATCH] Fix passing struct(float,struct(float,float)) on x86_64
|
||||
|
||||
The problem was that we assumed that structure elements never overlap
|
||||
eightbyte boundary. This assumption is violated by the above layout,
|
||||
where the first two floats should be passed in %xmm0 together.
|
||||
|
||||
This case is covered by the Itanium HFA tests func_hfa_f3 and func_hfa_f4.
|
||||
---
|
||||
ChangeLog | 4 +++
|
||||
sysdeps/linux-gnu/x86/fetch.c | 46 ++++++++++++++++++++++++++++++++++++----
|
||||
2 files changed, 45 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/linux-gnu/x86/fetch.c b/sysdeps/linux-gnu/x86/fetch.c
|
||||
index 8df900e..cca1638 100644
|
||||
--- a/sysdeps/linux-gnu/x86/fetch.c
|
||||
+++ b/sysdeps/linux-gnu/x86/fetch.c
|
||||
@@ -411,12 +411,34 @@ get_array_field(struct arg_type_info *info, size_t emt)
|
||||
return info->u.array_info.elt_type;
|
||||
}
|
||||
|
||||
+static int
|
||||
+flatten_structure(struct arg_type_info *flattened, struct arg_type_info *info)
|
||||
+{
|
||||
+ size_t i;
|
||||
+ for (i = 0; i < type_struct_size(info); ++i) {
|
||||
+ struct arg_type_info *field = type_struct_get(info, i);
|
||||
+ assert(field != NULL);
|
||||
+ switch (field->type) {
|
||||
+ case ARGTYPE_STRUCT:
|
||||
+ if (flatten_structure(flattened, field) < 0)
|
||||
+ return -1;
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ if (type_struct_add(flattened, field, 0) < 0)
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static ssize_t
|
||||
classify(struct Process *proc, struct fetch_context *context,
|
||||
struct arg_type_info *info, struct value *valuep, enum arg_class classes[],
|
||||
size_t sz, size_t eightbytes)
|
||||
{
|
||||
switch (info->type) {
|
||||
+ struct arg_type_info flattened;
|
||||
case ARGTYPE_VOID:
|
||||
return 0;
|
||||
|
||||
@@ -458,11 +480,25 @@ classify(struct Process *proc, struct fetch_context *context,
|
||||
get_array_field);
|
||||
|
||||
case ARGTYPE_STRUCT:
|
||||
- /* N.B. "big" structs are dealt with in the
|
||||
- * caller. */
|
||||
- return classify_eightbytes(proc, context, info, valuep, classes,
|
||||
- type_struct_size(info),
|
||||
- eightbytes, type_struct_get);
|
||||
+ /* N.B. "big" structs are dealt with in the caller.
|
||||
+ *
|
||||
+ * First, we need to flatten the structure. In
|
||||
+ * struct(float,struct(float,float)), first two floats
|
||||
+ * both belong to the same eightbyte. */
|
||||
+ type_init_struct(&flattened);
|
||||
+
|
||||
+ ssize_t ret;
|
||||
+ if (flatten_structure(&flattened, info) < 0) {
|
||||
+ ret = -1;
|
||||
+ goto done;
|
||||
+ }
|
||||
+ ret = classify_eightbytes(proc, context, &flattened,
|
||||
+ valuep, classes,
|
||||
+ type_struct_size(&flattened),
|
||||
+ eightbytes, type_struct_get);
|
||||
+ done:
|
||||
+ type_destroy(&flattened);
|
||||
+ return ret;
|
||||
}
|
||||
abort();
|
||||
}
|
||||
--
|
||||
1.7.6.5
|
||||
|
||||
150
ltrace-0.7.0-man5.patch
Normal file
150
ltrace-0.7.0-man5.patch
Normal file
@ -0,0 +1,150 @@
|
||||
diff -urp ltrace-0.7.0/Makefile.am ltrace-0.7.0/Makefile.am
|
||||
--- ltrace-0.7.0/Makefile.am 2012-11-10 13:43:55.000000000 +0100
|
||||
+++ ltrace-0.7.0/Makefile.am 2012-11-10 14:57:39.141288149 +0100
|
||||
@@ -116,7 +116,8 @@ noinst_HEADERS = \
|
||||
lens_default.h \
|
||||
lens_enum.h
|
||||
|
||||
-dist_man1_MANS = ltrace.1 ltrace.conf.5
|
||||
+dist_man1_MANS = ltrace.1
|
||||
+dist_man5_MANS = ltrace.conf.5
|
||||
|
||||
dist_doc_DATA = COPYING CREDITS INSTALL README TODO
|
||||
|
||||
diff -urp ltrace-0.7.0/Makefile.in ltrace-0.7.0/Makefile.in
|
||||
--- ltrace-0.7.0/Makefile.in 2012-11-10 13:46:03.000000000 +0100
|
||||
+++ ltrace-0.7.0/Makefile.in 2012-11-10 15:00:05.854225673 +0100
|
||||
@@ -60,8 +60,8 @@ host_triplet = @host@
|
||||
bin_PROGRAMS = ltrace$(EXEEXT)
|
||||
subdir = .
|
||||
DIST_COMMON = README $(am__configure_deps) $(dist_doc_DATA) \
|
||||
- $(dist_man1_MANS) $(dist_sysconf_DATA) $(noinst_HEADERS) \
|
||||
- $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
|
||||
+ $(dist_man1_MANS) $(dist_man5_MANS) $(dist_sysconf_DATA) \
|
||||
+ $(noinst_HEADERS) $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
|
||||
$(srcdir)/config.h.in $(top_srcdir)/configure COPYING INSTALL \
|
||||
NEWS TODO config/autoconf/config.guess \
|
||||
config/autoconf/config.sub config/autoconf/depcomp \
|
||||
@@ -96,7 +96,8 @@ am_libltrace_la_OBJECTS = breakpoints.lo
|
||||
lens_default.lo lens_enum.lo
|
||||
libltrace_la_OBJECTS = $(am_libltrace_la_OBJECTS)
|
||||
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" \
|
||||
- "$(DESTDIR)$(docdir)" "$(DESTDIR)$(sysconfdir)"
|
||||
+ "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(docdir)" \
|
||||
+ "$(DESTDIR)$(sysconfdir)"
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am_ltrace_OBJECTS = main.$(OBJEXT)
|
||||
ltrace_OBJECTS = $(am_ltrace_OBJECTS)
|
||||
@@ -145,8 +146,9 @@ am__base_list = \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||
man1dir = $(mandir)/man1
|
||||
+man5dir = $(mandir)/man5
|
||||
NROFF = nroff
|
||||
-MANS = $(dist_man1_MANS)
|
||||
+MANS = $(dist_man1_MANS) $(dist_man5_MANS)
|
||||
DATA = $(dist_doc_DATA) $(dist_sysconf_DATA)
|
||||
HEADERS = $(noinst_HEADERS)
|
||||
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
|
||||
@@ -410,7 +412,8 @@ noinst_HEADERS = \
|
||||
lens_default.h \
|
||||
lens_enum.h
|
||||
|
||||
-dist_man1_MANS = ltrace.1 ltrace.conf.5
|
||||
+dist_man1_MANS = ltrace.1
|
||||
+dist_man5_MANS = ltrace.conf.5
|
||||
dist_doc_DATA = COPYING CREDITS INSTALL README TODO
|
||||
dist_sysconf_DATA = \
|
||||
etc/ltrace.conf
|
||||
@@ -658,6 +661,40 @@ uninstall-man1:
|
||||
test -z "$$files" || { \
|
||||
echo " ( cd '$(DESTDIR)$(man1dir)' && rm -f" $$files ")"; \
|
||||
cd "$(DESTDIR)$(man1dir)" && rm -f $$files; }
|
||||
+install-man5: $(dist_man5_MANS)
|
||||
+ @$(NORMAL_INSTALL)
|
||||
+ test -z "$(man5dir)" || $(MKDIR_P) "$(DESTDIR)$(man5dir)"
|
||||
+ @list='$(dist_man5_MANS)'; test -n "$(man5dir)" || exit 0; \
|
||||
+ { for i in $$list; do echo "$$i"; done; \
|
||||
+ } | while read p; do \
|
||||
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
|
||||
+ echo "$$d$$p"; echo "$$p"; \
|
||||
+ done | \
|
||||
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
|
||||
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
|
||||
+ sed 'N;N;s,\n, ,g' | { \
|
||||
+ list=; while read file base inst; do \
|
||||
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
|
||||
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
|
||||
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \
|
||||
+ fi; \
|
||||
+ done; \
|
||||
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
|
||||
+ while read files; do \
|
||||
+ test -z "$$files" || { \
|
||||
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \
|
||||
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \
|
||||
+ done; }
|
||||
+
|
||||
+uninstall-man5:
|
||||
+ @$(NORMAL_UNINSTALL)
|
||||
+ @list='$(dist_man5_MANS)'; test -n "$(man5dir)" || exit 0; \
|
||||
+ files=`{ for i in $$list; do echo "$$i"; done; \
|
||||
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
|
||||
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
|
||||
+ test -z "$$files" || { \
|
||||
+ echo " ( cd '$(DESTDIR)$(man5dir)' && rm -f" $$files ")"; \
|
||||
+ cd "$(DESTDIR)$(man5dir)" && rm -f $$files; }
|
||||
install-dist_docDATA: $(dist_doc_DATA)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(docdir)" || $(MKDIR_P) "$(DESTDIR)$(docdir)"
|
||||
@@ -1028,7 +1065,7 @@ all-am: Makefile $(LTLIBRARIES) $(PROGRA
|
||||
config.h
|
||||
installdirs: installdirs-recursive
|
||||
installdirs-am:
|
||||
- for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(sysconfdir)"; do \
|
||||
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(sysconfdir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-recursive
|
||||
@@ -1097,7 +1134,7 @@ install-info: install-info-recursive
|
||||
|
||||
install-info-am:
|
||||
|
||||
-install-man: install-man1
|
||||
+install-man: install-man1 install-man5
|
||||
|
||||
install-pdf: install-pdf-recursive
|
||||
|
||||
@@ -1133,7 +1170,7 @@ ps-am:
|
||||
uninstall-am: uninstall-binPROGRAMS uninstall-dist_docDATA \
|
||||
uninstall-dist_sysconfDATA uninstall-man
|
||||
|
||||
-uninstall-man: uninstall-man1
|
||||
+uninstall-man: uninstall-man1 uninstall-man5
|
||||
|
||||
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \
|
||||
ctags-recursive install-am install-strip tags-recursive
|
||||
@@ -1150,14 +1187,16 @@ uninstall-man: uninstall-man1
|
||||
install-data-am install-dist_docDATA install-dist_sysconfDATA \
|
||||
install-dvi install-dvi-am install-exec install-exec-am \
|
||||
install-html install-html-am install-info install-info-am \
|
||||
- install-man install-man1 install-pdf install-pdf-am install-ps \
|
||||
- install-ps-am install-strip installcheck installcheck-am \
|
||||
- installdirs installdirs-am maintainer-clean \
|
||||
- maintainer-clean-generic maintainer-clean-local mostlyclean \
|
||||
- mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
|
||||
- pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
|
||||
+ install-man install-man1 install-man5 install-pdf \
|
||||
+ install-pdf-am install-ps install-ps-am install-strip \
|
||||
+ installcheck installcheck-am installdirs installdirs-am \
|
||||
+ maintainer-clean maintainer-clean-generic \
|
||||
+ maintainer-clean-local mostlyclean mostlyclean-compile \
|
||||
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||
+ tags tags-recursive uninstall uninstall-am \
|
||||
uninstall-binPROGRAMS uninstall-dist_docDATA \
|
||||
- uninstall-dist_sysconfDATA uninstall-man uninstall-man1
|
||||
+ uninstall-dist_sysconfDATA uninstall-man uninstall-man1 \
|
||||
+ uninstall-man5
|
||||
|
||||
|
||||
maintainer-clean-local:
|
||||
70
ltrace-0.7.0-ppc-insn.h.patch
Normal file
70
ltrace-0.7.0-ppc-insn.h.patch
Normal file
@ -0,0 +1,70 @@
|
||||
diff -urp ltrace-0.7.0/sysdeps/linux-gnu/ppc/Makefile.am ltrace-0.7.0/sysdeps/linux-gnu/ppc/Makefile.am
|
||||
--- ltrace-0.7.0/sysdeps/linux-gnu/ppc/Makefile.am 2012-11-09 23:45:23.192038441 +0100
|
||||
+++ ltrace-0.7.0/sysdeps/linux-gnu/ppc/Makefile.am 2012-11-10 13:43:55.000000000 +0100
|
||||
@@ -27,6 +27,7 @@ ___libcpu_la_SOURCES = \
|
||||
|
||||
noinst_HEADERS = \
|
||||
arch.h \
|
||||
+ insn.h \
|
||||
ptrace.h \
|
||||
signalent.h \
|
||||
syscallent.h
|
||||
diff -urp ltrace-0.7.0/sysdeps/linux-gnu/ppc/Makefile.in ltrace-0.7.0/sysdeps/linux-gnu/ppc/Makefile.in
|
||||
--- ltrace-0.7.0/sysdeps/linux-gnu/ppc/Makefile.in 2012-11-10 14:41:22.453856321 +0100
|
||||
+++ ltrace-0.7.0/sysdeps/linux-gnu/ppc/Makefile.in 2012-11-10 13:46:03.000000000 +0100
|
||||
@@ -232,6 +232,7 @@ ___libcpu_la_SOURCES = \
|
||||
|
||||
noinst_HEADERS = \
|
||||
arch.h \
|
||||
+ insn.h \
|
||||
ptrace.h \
|
||||
signalent.h \
|
||||
syscallent.h
|
||||
--- ltrace-0.7.0/sysdeps/linux-gnu/ppc/insn.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ ltrace-0.7.0/sysdeps/linux-gnu/ppc/insn.h 2012-11-07 17:09:31.784520698 +0100
|
||||
@@ -0,0 +1,45 @@
|
||||
+/*
|
||||
+ * This file is part of ltrace.
|
||||
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 2 of the
|
||||
+ * License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful, but
|
||||
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, write to the Free Software
|
||||
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
+ * 02110-1301 USA
|
||||
+ */
|
||||
+
|
||||
+/* Instruction masks used during single-stepping of atomic
|
||||
+ * sequences. This was lifted from GDB. */
|
||||
+#define LWARX_MASK 0xfc0007fe
|
||||
+#define LWARX_INSTRUCTION 0x7c000028
|
||||
+#define LDARX_INSTRUCTION 0x7c0000A8
|
||||
+#define STWCX_MASK 0xfc0007ff
|
||||
+#define STWCX_INSTRUCTION 0x7c00012d
|
||||
+#define STDCX_INSTRUCTION 0x7c0001ad
|
||||
+#define BRANCH_MASK 0xfc000000
|
||||
+#define BC_MASK 0xfc000000
|
||||
+#define BC_INSN 0x40000000
|
||||
+#define B_INSN 0x48000000
|
||||
+
|
||||
+static inline arch_addr_t
|
||||
+ppc_branch_dest(arch_addr_t addr, uint32_t insn)
|
||||
+{
|
||||
+ int immediate = ((insn & 0xfffc) ^ 0x8000) - 0x8000;
|
||||
+ int absolute = insn & 2;
|
||||
+
|
||||
+ /* XXX drop the following double casts. */
|
||||
+ if (absolute)
|
||||
+ return (arch_addr_t)(uintptr_t)immediate;
|
||||
+ else
|
||||
+ return addr + (uintptr_t)immediate;
|
||||
+}
|
||||
80
ltrace.spec
80
ltrace.spec
@ -1,47 +1,20 @@
|
||||
Summary: Tracks runtime library calls from dynamically linked executables
|
||||
Name: ltrace
|
||||
Version: 0.6.0
|
||||
Release: 19%{?dist}
|
||||
Version: 0.7.0
|
||||
Release: 1%{?dist}
|
||||
URL: http://ltrace.alioth.debian.org/
|
||||
License: GPLv2+
|
||||
Group: Development/Debuggers
|
||||
|
||||
BuildRequires: elfutils-libelf-devel dejagnu
|
||||
BuildRequires: autoconf automake libtool
|
||||
BuildRequires: libselinux-devel
|
||||
|
||||
# Tarball generated from git checkout. To regenerate:
|
||||
# git clone http://github.com/ice799/ltrace.git
|
||||
# cd ltrace && ./autogen.sh && ./configure && make dist
|
||||
Source: %{name}-%{version}.tar.bz2
|
||||
Source: http://alioth.debian.org/frs/download.php/3822/%{name}-%{version}.tar.bz2
|
||||
|
||||
Patch1: ltrace-0.5-ia64-sigill.patch
|
||||
Patch2: ltrace-0.6.0-exec-stripped.patch
|
||||
Patch4: ltrace-0.5-etc-memmove.patch
|
||||
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
|
||||
Patch11: ltrace-0.6.0-vfork.patch
|
||||
Patch12: ltrace-0.6.0-thread-races.patch
|
||||
Patch13: ltrace-0.6.0-process-start.patch
|
||||
Patch14: ltrace-0.6.0-selinux.patch
|
||||
Patch15: ltrace-0.6.0-detach-sleeping.patch
|
||||
Patch16: ltrace-0.6.0-tail-return.patch
|
||||
Patch17: ltrace-0.6.0-ppc-lwarx.patch
|
||||
Patch18: ltrace-0.6.0-libs.patch
|
||||
Patch19: ltrace-0.6.0-libs-fixes-1.patch
|
||||
Patch20: ltrace-0.6.0-dash-n.patch
|
||||
Patch21: ltrace-0.6.0-demangle.patch
|
||||
Patch22: ltrace-0.6.0-abi.patch
|
||||
Patch23: ltrace-0.6.0-abi-s390.patch
|
||||
Patch24: ltrace-0.6.0-ppc-flteqv.patch
|
||||
Patch25: ltrace-0.6.0-cleanups.patch
|
||||
Patch26: ltrace-0.6.0-syscall-time.patch
|
||||
Patch27: ltrace-0.6.0-abi-ia64.patch
|
||||
Patch28: ltrace-0.6.0-x86_64-flatten.patch
|
||||
Patch29: ltrace-0.6.0-dash-l.patch
|
||||
# Upstream ccbdb91f
|
||||
Patch0: ltrace-0.7.0-ppc-insn.h.patch
|
||||
# Upstream 808d64b9
|
||||
Patch1: ltrace-0.7.0-man5.patch
|
||||
|
||||
%description
|
||||
Ltrace is a debugging program which runs a specified command until the
|
||||
@ -55,39 +28,13 @@ execution of processes.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
%patch0 -p1
|
||||
%patch1 -p1
|
||||
%patch2 -p1
|
||||
%patch4 -p1
|
||||
%patch5 -p1
|
||||
%patch6 -p1
|
||||
%patch7 -p1
|
||||
%patch8 -p1
|
||||
%patch9 -p1
|
||||
%patch11 -p1
|
||||
%patch12 -p1
|
||||
%patch13 -p1
|
||||
%patch14 -p1
|
||||
%patch15 -p1
|
||||
%patch16 -p1
|
||||
%patch17 -p1
|
||||
%patch18 -p1
|
||||
%patch19 -p1
|
||||
%patch20 -p1
|
||||
%patch21 -p1
|
||||
%patch22 -p1
|
||||
%patch23 -p1
|
||||
%patch24 -p1
|
||||
%patch25 -p1
|
||||
%patch26 -p1
|
||||
%patch27 -p1
|
||||
%patch28 -p1
|
||||
%patch29 -p1
|
||||
|
||||
%build
|
||||
# This ugly hack is necessary to build and link files for correct
|
||||
# architecture. It makes a difference on ppc.
|
||||
export CC="gcc`echo $RPM_OPT_FLAGS | sed -n 's/^.*\(-m[36][124]\).*$/ \1/p'` -D_LARGEFILE64_SOURCE"
|
||||
autoreconf -i
|
||||
%configure CC="$CC"
|
||||
make %{?_smp_mflags}
|
||||
|
||||
@ -103,12 +50,21 @@ echo ====================TESTING END=====================
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%doc COPYING README TODO BUGS ChangeLog
|
||||
%doc COPYING README NEWS
|
||||
%{_bindir}/ltrace
|
||||
%{_mandir}/man1/ltrace.1*
|
||||
%{_mandir}/man5/ltrace.conf.5*
|
||||
%config(noreplace) %{_sysconfdir}/ltrace.conf
|
||||
|
||||
%changelog
|
||||
* Sat Nov 10 2012 Petr Machata <pmachata@redhat.com> - 0.7.0-1
|
||||
- Upstream 0.7.0
|
||||
- Drop all the patches
|
||||
- Upstream patch for missing sysdeps/linux-gnu/ppc/insn.h
|
||||
(ltrace-0.7.0-ppc-insn.h.patch)
|
||||
- Upstream patch for installing ltrace.conf.5 to man5
|
||||
(ltrace-0.7.0-man5.patch)
|
||||
|
||||
* Mon Oct 1 2012 Petr Machata <pmachata@redhat.com> - 0.6.0-19
|
||||
- Upstream patch for ia64 parameter passing
|
||||
(ltrace-0.6.0-abi-ia64.patch)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user