Package init

This commit is contained in:
sigui 2020-02-21 02:22:29 +08:00
parent 30d3bb0b5a
commit ddc1daa205
21 changed files with 5078 additions and 0 deletions

View File

@ -0,0 +1,12 @@
diff --git a/configure.ac b/configure.ac
index 6853a0b..78faeed 100644
--- a/configure.ac
+++ b/configure.ac
@@ -41,6 +41,7 @@AC_SUBST(HOST_OS)
case "${host_cpu}" in
arm*|sa110) HOST_CPU="arm" ;;
+ aarch64_be) HOST_CPU="aarch64" ;;
cris*) HOST_CPU="cris" ;;
mips*) HOST_CPU="mips" ;;
powerpc|powerpc64) HOST_CPU="ppc" ;;

View File

@ -0,0 +1,20 @@
diff --git a/sysdeps/linux-gnu/arm/trace.c b/sysdeps/linux-gnu/arm/trace.c
index f974d1f..8526bf1 100644
--- a/sysdeps/linux-gnu/arm/trace.c
+++ b/sysdeps/linux-gnu/arm/trace.c
@@ -77,6 +77,15 @@ syscall_p(struct process *proc, int status, int *sysnum)
unsigned insn = ptrace(PTRACE_PEEKTEXT, proc->pid,
(void *)pc, 0);
+#if defined(__ARMEB__) && defined(__ARM_ARCH_7A__)
+ /* We running big endian arm on ARMv7: instructions are
+ * in little endian form so we need to byteswap it. Note
+ * on older ARM like V5 Xscale code is in big endian form
+ * byte swap is not needed in this case. I.e be8 vs be32.
+ */
+ insn = __builtin_bswap32(insn);
+#endif /* __ARMEB__ && __ARM_ARCH_7A__ */
+
if (insn == 0xef000000 || insn == 0x0f000000
|| (insn & 0xffff0000) == 0xdf000000) {
/* EABI syscall */

View File

@ -0,0 +1,141 @@
From 8eccd30f5d3ae0be17f2a75116600f5fca9c76db Mon Sep 17 00:00:00 2001
From: root <root@localhost.localdomain>
Date: Sat, 4 May 2019 16:51:52 +0800
Subject: [PATCH] bugfix for use after free about soname
==18904==ERROR: AddressSanitizer: heap-use-after-free on address 0xffffa0d00313 at pc 0xffffa3d1bc70 bp 0xffffe9c118d0 sp 0xffffe9c11948
READ of size 5 at 0xffffa0d00313 thread T0
#0 0xffffa3d1bc6f (/usr/lib64/libasan.so.4+0x50c6f)
#1 0xaaaae94e1d67 in library_get_prototype /root/rpmbuild/BUILD/ltrace-0.7.91/output.c:198
#2 0xaaaae94e2f8f in lookup_symbol_prototype /root/rpmbuild/BUILD/ltrace-0.7.91/output.c:243
#3 0xaaaae94e383b in lookup_symbol_prototype /root/rpmbuild/BUILD/ltrace-0.7.91/output.c:703
#4 0xaaaae94e383b in output_right /root/rpmbuild/BUILD/ltrace-0.7.91/output.c:644
#5 0xaaaae94e08d3 in output_right_tos /root/rpmbuild/BUILD/ltrace-0.7.91/handle_event.c:665
#6 0xaaaae94e1a4f in handle_breakpoint /root/rpmbuild/BUILD/ltrace-0.7.91/handle_event.c:703
#7 0xaaaae94e1a4f in handle_event /root/rpmbuild/BUILD/ltrace-0.7.91/handle_event.c:200
#8 0xaaaae94ce237 in ltrace_main /root/rpmbuild/BUILD/ltrace-0.7.91/libltrace.c:174
#9 0xaaaae94cdd1f in main /root/rpmbuild/BUILD/ltrace-0.7.91/main.c:55
#10 0xffffa38ecadf in __libc_start_main (/lib64/libc.so.6+0x20adf)
#11 0xaaaae94cdd5f (/ltrace+0x9d5f)
0xffffa0d00313 is located 3 bytes inside of 8-byte region [0xffffa0d00310,0xffffa0d00318)
freed by thread T0 here:
#0 0xffffa3d9b6c3 in free (/usr/lib64/libasan.so.4+0xd06c3)
#1 0xaaaae94d101f in private_process_destroy /root/rpmbuild/BUILD/ltrace-0.7.91/proc.c:273
#2 0xaaaae94d10ab in remove_process /root/rpmbuild/BUILD/ltrace-0.7.91/proc.c:753
#3 0xaaaae94e0d73 in handle_exit_signal /root/rpmbuild/BUILD/ltrace-0.7.91/handle_event.c:521
#4 0xaaaae94e0d73 in handle_event /root/rpmbuild/BUILD/ltrace-0.7.91/handle_event.c:142
#5 0xaaaae94ce237 in ltrace_main /root/rpmbuild/BUILD/ltrace-0.7.91/libltrace.c:174
#6 0xaaaae94cdd1f in main /root/rpmbuild/BUILD/ltrace-0.7.91/main.c:55
#7 0xffffa38ecadf in __libc_start_main (/lib64/libc.so.6+0x20adf)
#8 0xaaaae94cdd5f (/ltrace+0x9d5f)
previously allocated by thread T0 here:
#0 0xffffa3d3e34f in strdup (/usr/lib64/libasan.so.4+0x7334f)
#1 0xaaaae94cfb2b in process_bare_init /root/rpmbuild/BUILD/ltrace-0.7.91/proc.c:128
#2 0xaaaae94cfcbf in process_init /root/rpmbuild/BUILD/ltrace-0.7.91/proc.c:214
#3 0xaaaae94cfe17 in open_program /root/rpmbuild/BUILD/ltrace-0.7.91/proc.c:330
#4 0xaaaae94ce09f in ltrace_init /root/rpmbuild/BUILD/ltrace-0.7.91/libltrace.c:125
#5 0xaaaae94cdd1b in main /root/rpmbuild/BUILD/ltrace-0.7.91/main.c:47
#6 0xffffa38ecadf in __libc_start_main (/lib64/libc.so.6+0x20adf)
#7 0xaaaae94cdd5f (/ltrace+0x9d5f)
SUMMARY: AddressSanitizer: heap-use-after-free (/usr/lib64/libasan.so.4+0x50c6f)
Shadow bytes around the buggy address:
0x200ff41a0010: fa fa fd fa fa fa fd fa fa fa fd fa fa fa 00 00
0x200ff41a0020: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 00 00
0x200ff41a0030: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 00 00
0x200ff41a0040: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 00 00
0x200ff41a0050: fa fa 00 00 fa fa fd fa fa fa fd fa fa fa fd fd
=>0x200ff41a0060: fa fa[fd]fa fa fa 00 07 fa fa 06 fa fa fa 05 fa
0x200ff41a0070: fa fa 00 00 fa fa 05 fa fa fa 00 00 fa fa 00 00
0x200ff41a0080: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 01 fa
0x200ff41a0090: fa fa 00 00 fa fa 00 00 fa fa 01 fa fa fa 00 00
0x200ff41a00a0: fa fa 04 fa fa fa 04 fa fa fa 00 fa fa fa fd fd
0x200ff41a00b0: fa fa 04 fa fa fa 04 fa fa fa 00 fa fa fa 04 fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
=================================================================
==18904==ERROR: AddressSanitizer: heap-use-after-free on address 0xffffa0d00313 at pc 0xffffa3d3fbe4 bp 0xffffe9c118c0 sp 0xffffe9c11938
READ of size 5 at 0xffffa0d00313 thread T0
#0 0xffffa3d3fbe3 (/usr/lib64/libasan.so.4+0x74be3)
#1 0xaaaae94e1db3 in memcpy /usr/include/bits/string_fortified.h:34
#2 0xaaaae94e1db3 in library_get_prototype /root/rpmbuild/BUILD/ltrace-0.7.91/output.c:200
#3 0xaaaae94e2f8f in lookup_symbol_prototype /root/rpmbuild/BUILD/ltrace-0.7.91/output.c:243
#4 0xaaaae94e383b in lookup_symbol_prototype /root/rpmbuild/BUILD/ltrace-0.7.91/output.c:703
#5 0xaaaae94e383b in output_right /root/rpmbuild/BUILD/ltrace-0.7.91/output.c:644
#6 0xaaaae94e08d3 in output_right_tos /root/rpmbuild/BUILD/ltrace-0.7.91/handle_event.c:665
#7 0xaaaae94e1a4f in handle_breakpoint /root/rpmbuild/BUILD/ltrace-0.7.91/handle_event.c:703
#8 0xaaaae94e1a4f in handle_event /root/rpmbuild/BUILD/ltrace-0.7.91/handle_event.c:200
#9 0xaaaae94ce237 in ltrace_main /root/rpmbuild/BUILD/ltrace-0.7.91/libltrace.c:174
#10 0xaaaae94cdd1f in main /root/rpmbuild/BUILD/ltrace-0.7.91/main.c:55
#11 0xffffa38ecadf in __libc_start_main (/lib64/libc.so.6+0x20adf)
#12 0xaaaae94cdd5f (/ltrace+0x9d5f)
0xffffa0d00313 is located 3 bytes inside of 8-byte region [0xffffa0d00310,0xffffa0d00318)
freed by thread T0 here:
#0 0xffffa3d9b6c3 in free (/usr/lib64/libasan.so.4+0xd06c3)
#1 0xaaaae94d101f in private_process_destroy /root/rpmbuild/BUILD/ltrace-0.7.91/proc.c:273
#2 0xaaaae94d10ab in remove_process /root/rpmbuild/BUILD/ltrace-0.7.91/proc.c:753
#3 0xaaaae94e0d73 in handle_exit_signal /root/rpmbuild/BUILD/ltrace-0.7.91/handle_event.c:521
#4 0xaaaae94e0d73 in handle_event /root/rpmbuild/BUILD/ltrace-0.7.91/handle_event.c:142
#5 0xaaaae94ce237 in ltrace_main /root/rpmbuild/BUILD/ltrace-0.7.91/libltrace.c:174
#6 0xaaaae94cdd1f in main /root/rpmbuild/BUILD/ltrace-0.7.91/main.c:55
#7 0xffffa38ecadf in __libc_start_main (/lib64/libc.so.6+0x20adf)
#8 0xaaaae94cdd5f (/ltrace+0x9d5f)
previously allocated by thread T0 here:
#0 0xffffa3d3e34f in strdup (/usr/lib64/libasan.so.4+0x7334f)
#1 0xaaaae94cfb2b in process_bare_init /root/rpmbuild/BUILD/ltrace-0.7.91/proc.c:128
#2 0xaaaae94cfcbf in process_init /root/rpmbuild/BUILD/ltrace-0.7.91/proc.c:214
#3 0xaaaae94cfe17 in open_program /root/rpmbuild/BUILD/ltrace-0.7.91/proc.c:330
#4 0xaaaae94ce09f in ltrace_init /root/rpmbuild/BUILD/ltrace-0.7.91/libltrace.c:125
#5 0xaaaae94cdd1b in main /root/rpmbuild/BUILD/ltrace-0.7.91/main.c:47
#6 0xffffa38ecadf in __libc_start_main (/lib64/libc.so.6+0x20adf)
#7 0xaaaae94cdd5f (/ltrace+0x9d5f)
SUMMARY: AddressSanitizer: heap-use-after-free (/usr/lib64/libasan.so.4+0x74be3)
---
ltrace-elf.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/ltrace-elf.c b/ltrace-elf.c
index f638342..286790a 100644
--- a/ltrace-elf.c
+++ b/ltrace-elf.c
@@ -1214,12 +1214,14 @@ read_module(struct library *lib, struct process *proc,
goto fail;
library_set_soname(lib, soname, 1);
} else {
+ char *soname_str = NULL;
const char *soname = rindex(lib->pathname, '/');
if (soname != NULL)
soname += 1;
else
soname = lib->pathname;
- library_set_soname(lib, soname, 0);
+ soname_str = strdup(soname);
+ library_set_soname(lib, soname_str, 1);
}
/* XXX The double cast should be removed when
--
2.19.1

View File

@ -0,0 +1,20 @@
diff -up ltrace-0.7.2/proc.c\~ ltrace-0.7.2/proc.c
--- ltrace-0.7.2/proc.c~ 2014-02-13 12:16:33.000000000 +0100
+++ ltrace-0.7.2/proc.c 2014-02-13 15:44:25.000000000 +0100
@@ -194,9 +197,11 @@ process_init(struct process *proc, const
goto fail;
}
- if (proc->leader != proc)
- return 0;
- if (process_init_main(proc) < 0) {
+ if (proc->leader != proc) {
+ proc->e_machine = proc->leader->e_machine;
+ proc->e_class = proc->leader->e_class;
+ get_arch_dep(proc);
+ } else if (process_init_main(proc) < 0) {
process_bare_destroy(proc, 0);
goto fail;
}
Diff finished. Thu Feb 13 15:50:21 2014

View File

@ -0,0 +1,37 @@
diff -rup a/sysdeps/linux-gnu/aarch64/fetch.c b/sysdeps/linux-gnu/aarch64/fetch.c
--- a/sysdeps/linux-gnu/aarch64/fetch.c 2018-07-05 16:06:10.066626252 -0400
+++ b/sysdeps/linux-gnu/aarch64/fetch.c 2018-07-05 16:17:17.659748481 -0400
@@ -308,12 +308,9 @@ arch_fetch_arg_init(enum tof type, struc
struct fetch_script how = pass_arg(context, proc, ret_info);
if (how.c == CVT_ERR)
goto fail;
- if (how.c == CVT_NOP && how.f == FETCH_STACK) {
+ if (how.c == CVT_BYREF && how.f == FETCH_GPR) {
/* XXX double cast. */
context->x8 = (arch_addr_t) (uintptr_t) context->gregs.regs[8];
- /* See the comment above about the assert. */
- assert(! "Unexpected: first argument passed on stack.");
- abort();
}
return context;
diff -rup a/testsuite/ltrace.main/system_call_params.exp b/testsuite/ltrace.main/system_call_params.exp
--- a/testsuite/ltrace.main/system_call_params.exp 2018-07-05 16:06:10.516624926 -0400
+++ b/testsuite/ltrace.main/system_call_params.exp 2018-07-05 16:58:01.549830643 -0400
@@ -61,13 +61,13 @@ set conf [ltraceNamedSource "$dir/syscal
# doesn't list readdir, that would be taken from somelib.conf with a
# wrong prototype.
-ltraceMatch1 [ltraceRun -L -S -F $conf -- $bin] {^open@SYS\("/some/path"} == 0
+ltraceMatch1 [ltraceRun -L -S -F $conf -- $bin] {^open@SYS\("/some/path", 0\)} == 0
# On the other hand, if -F somedir/ is given, we want to accept
# syscalls.conf found there.
ltraceMatch [ltraceRun -L -S -F $dir -- $bin] {
- {{^open@SYS\("/some/path"} == 1}
+ {{^open@SYS\("/some/path", 0\)} == 1}
{{^write@SYS\(1, "something", 10\)} == 1}
{{^mount@SYS\("source", "target", "filesystemtype"} == 1}
}
Only in b/testsuite/ltrace.main: system_call_params.exp~

2416
ltrace-0.7.91-aarch64.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,834 @@
From 0cf4ab66e9927e101a51dd9fa9adc6c8dc56b5e7 Mon Sep 17 00:00:00 2001
From: Petr Machata <pmachata@redhat.com>
Date: Thu, 21 Nov 2013 20:25:53 +0100
Subject: [PATCH] Consider exec and exit events an end of outstanding calls
- This cleans up a lot of stuff. The actual substance is addition of
account_current_callstack in handle_event.c (which however uses
those cleaned-up interfaces).
- trace-exec.exp was extended to check that the exec syscall can be
seen in -c output. That's one of the symptoms of what this fixes.
---
Makefile.am | 8 +-
common.h | 2 -
forward.h | 1 +
handle_event.c | 225 ++++++++++++++++++++-------------
libltrace.c | 5 +-
options.h | 8 +-
output.c | 86 +++----------
output.h | 5 +-
proc.h | 2 +-
summary.c | 89 +++++++++++++-
summary.h | 35 +++++
testsuite/ltrace.minor/trace-exec.exp | 16 ++-
12 files changed, 299 insertions(+), 183 deletions(-)
create mode 100644 summary.h
diff --git a/Makefile.am b/Makefile.am
index d711aec..efcf18a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -54,10 +54,10 @@ ltrace_LDADD = \
noinst_HEADERS = bits.h backend.h breakpoint.h common.h debug.h \
defs.h demangle.h dict.h forward.h ltrace-elf.h ltrace.h \
- options.h output.h proc.h read_config_file.h library.h \
- filter.h glob.h vect.h type.h value.h value_dict.h callback.h \
- expr.h fetch.h vect.h param.h printf.h zero.h lens.h \
- lens_default.h lens_enum.h memstream.h prototype.h
+ options.h output.h proc.h read_config_file.h summary.h \
+ library.h filter.h glob.h vect.h type.h value.h value_dict.h \
+ callback.h expr.h fetch.h vect.h param.h printf.h zero.h \
+ lens.h lens_default.h lens_enum.h memstream.h prototype.h
dist_man1_MANS = ltrace.1
dist_man5_MANS = ltrace.conf.5
diff --git a/common.h b/common.h
index a53c5db..7259ba4 100644
--- a/common.h
+++ b/common.h
@@ -54,8 +54,6 @@ extern void handle_event(Event * event);
extern pid_t execute_program(const char * command, char ** argv);
-extern void show_summary(void);
-
struct breakpoint;
struct library_symbol;
diff --git a/forward.h b/forward.h
index 8641213..58d8f05 100644
--- a/forward.h
+++ b/forward.h
@@ -34,6 +34,7 @@ struct param_enum;
struct process;
struct protolib;
struct prototype;
+struct timedelta;
struct value;
struct value_dict;
struct vect;
diff --git a/handle_event.c b/handle_event.c
index 9ed62a2..6fa7e98 100644
--- a/handle_event.c
+++ b/handle_event.c
@@ -32,7 +32,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/time.h>
#include <stdbool.h>
#include "backend.h"
@@ -41,8 +40,9 @@
#include "fetch.h"
#include "library.h"
#include "proc.h"
-#include "value_dict.h"
#include "prototype.h"
+#include "summary.h"
+#include "value_dict.h"
static void handle_signal(Event *event);
static void handle_exit(Event *event);
@@ -419,32 +419,11 @@ handle_signal(Event *event) {
continue_after_signal(event->proc->pid, event->e_un.signum);
}
-static void
-handle_exit(Event *event) {
- debug(DEBUG_FUNCTION, "handle_exit(pid=%d, status=%d)", event->proc->pid, event->e_un.ret_val);
- if (event->proc->state != STATE_IGNORED) {
- output_line(event->proc, "+++ exited (status %d) +++",
- event->e_un.ret_val);
- }
- remove_process(event->proc);
-}
-
-static void
-handle_exit_signal(Event *event) {
- debug(DEBUG_FUNCTION, "handle_exit_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum);
- if (event->proc->state != STATE_IGNORED) {
- output_line(event->proc, "+++ killed by %s +++",
- shortsignal(event->proc, event->e_un.signum));
- }
- remove_process(event->proc);
-}
-
-static void
-output_syscall(struct process *proc, const char *name, enum tof tof,
- void (*output)(enum tof, struct process *,
- struct library_symbol *))
+static int
+init_syscall_symbol(struct library_symbol *libsym, const char *name)
{
static struct library syscall_lib;
+
if (syscall_lib.protolib == NULL) {
struct protolib *protolib
= protolib_cache_load(&g_protocache, "syscalls", 0, 1);
@@ -475,10 +454,91 @@ output_syscall(struct process *proc, const char *name, enum tof tof,
syscall_lib.protolib = protolib;
}
+ if (library_symbol_init(libsym, 0, name, 0, LS_TOPLT_NONE) < 0)
+ return -1;
+
+ libsym->lib = &syscall_lib;
+ return 0;
+}
+
+/* Account the unfinished functions on the call stack. */
+static void
+account_current_callstack(struct process *proc)
+{
+ if (! options.summary)
+ return;
+
+ struct timedelta spent[proc->callstack_depth];
+
+ size_t i;
+ for (i = 0; i < proc->callstack_depth; ++i) {
+ struct callstack_element *elem = &proc->callstack[i];
+ spent[i] = calc_time_spent(elem->enter_time);
+ }
+
+ for (i = 0; i < proc->callstack_depth; ++i) {
+ struct callstack_element *elem = &proc->callstack[i];
+ struct library_symbol syscall, *libsym = NULL;
+ if (elem->is_syscall) {
+ const char *name = sysname(proc, elem->c_un.syscall);
+ if (init_syscall_symbol(&syscall, name) >= 0)
+ libsym = &syscall;
+
+ } else {
+ libsym = elem->c_un.libfunc;
+ }
+
+ if (libsym != NULL) {
+ summary_account_call(libsym, spent[i]);
+
+ if (elem->is_syscall)
+ library_symbol_destroy(&syscall);
+ }
+ }
+}
+
+static void
+handle_exit(Event *event) {
+ debug(DEBUG_FUNCTION, "handle_exit(pid=%d, status=%d)", event->proc->pid, event->e_un.ret_val);
+ if (event->proc->state != STATE_IGNORED) {
+ output_line(event->proc, "+++ exited (status %d) +++",
+ event->e_un.ret_val);
+ }
+
+ account_current_callstack(event->proc);
+ remove_process(event->proc);
+}
+
+static void
+handle_exit_signal(Event *event) {
+ debug(DEBUG_FUNCTION, "handle_exit_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum);
+ if (event->proc->state != STATE_IGNORED) {
+ output_line(event->proc, "+++ killed by %s +++",
+ shortsignal(event->proc, event->e_un.signum));
+ }
+
+ account_current_callstack(event->proc);
+ remove_process(event->proc);
+}
+
+static void
+output_syscall(struct process *proc, const char *name, enum tof tof,
+ bool left, struct timedelta *spent)
+{
+ if (left)
+ assert(spent == NULL);
+
struct library_symbol syscall;
- if (library_symbol_init(&syscall, 0, name, 0, LS_TOPLT_NONE) >= 0) {
- syscall.lib = &syscall_lib;
- (*output)(tof, proc, &syscall);
+ if (init_syscall_symbol(&syscall, name) >= 0) {
+ if (left) {
+ if (! options.summary)
+ output_left(tof, proc, &syscall);
+ } else if (options.summary) {
+ summary_account_call(&syscall, *spent);
+ } else {
+ output_right(tof, proc, &syscall, spent);
+ }
+
library_symbol_destroy(&syscall);
}
}
@@ -486,17 +546,19 @@ output_syscall(struct process *proc, const char *name, enum tof tof,
static void
output_syscall_left(struct process *proc, const char *name)
{
- output_syscall(proc, name, LT_TOF_SYSCALL, &output_left);
+ output_syscall(proc, name, LT_TOF_SYSCALL, true, NULL);
}
static void
-output_syscall_right(struct process *proc, const char *name)
+output_syscall_right(struct process *proc, const char *name,
+ struct timedelta *spent)
{
- output_syscall(proc, name, LT_TOF_SYSCALLR, &output_right);
+ output_syscall(proc, name, LT_TOF_SYSCALLR, false, spent);
}
static void
-handle_syscall(Event *event) {
+handle_syscall(Event *event)
+{
debug(DEBUG_FUNCTION, "handle_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
if (event->proc->state != STATE_IGNORED) {
callstack_push_syscall(event->proc, event->e_un.sysnum);
@@ -526,6 +588,8 @@ handle_exec(Event *event)
}
output_line(proc, "--- Called exec() ---");
+ account_current_callstack(proc);
+
if (process_exec(proc) < 0) {
fprintf(stderr,
"couldn't reinitialize process %d after exec\n", pid);
@@ -549,74 +613,58 @@ handle_arch_syscall(Event *event) {
continue_process(event->proc->pid);
}
-struct timeval current_time_spent;
-
static void
-calc_time_spent(struct process *proc)
+handle_x_sysret(Event *event, char *(*name_cb)(struct process *, int))
{
- struct timeval tv;
- struct timezone tz;
- struct timeval diff;
- struct callstack_element *elem;
-
- debug(DEBUG_FUNCTION, "calc_time_spent(pid=%d)", proc->pid);
- elem = &proc->callstack[proc->callstack_depth - 1];
-
- gettimeofday(&tv, &tz);
+ debug(DEBUG_FUNCTION, "handle_x_sysret(pid=%d, sysnum=%d)",
+ event->proc->pid, event->e_un.sysnum);
- diff.tv_sec = tv.tv_sec - elem->time_spent.tv_sec;
- 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_usec = 1000000 + tv.tv_usec - elem->time_spent.tv_usec;
- }
- current_time_spent = diff;
-}
+ unsigned d = event->proc->callstack_depth;
+ assert(d > 0);
+ struct callstack_element *elem = &event->proc->callstack[d - 1];
+ assert(elem->is_syscall);
-static void
-handle_sysret(Event *event) {
- debug(DEBUG_FUNCTION, "handle_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
if (event->proc->state != STATE_IGNORED) {
- if (opt_T || options.summary) {
- calc_time_spent(event->proc);
- }
+ struct timedelta spent = calc_time_spent(elem->enter_time);
if (options.syscalls)
output_syscall_right(event->proc,
- sysname(event->proc,
- event->e_un.sysnum));
+ name_cb(event->proc,
+ event->e_un.sysnum),
+ &spent);
- 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_after_syscall(event->proc, event->e_un.sysnum, 1);
}
static void
-handle_arch_sysret(Event *event) {
- debug(DEBUG_FUNCTION, "handle_arch_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
- if (event->proc->state != STATE_IGNORED) {
- if (opt_T || options.summary) {
- calc_time_spent(event->proc);
- }
- if (options.syscalls)
- output_syscall_right(event->proc,
- arch_sysname(event->proc,
- event->e_un.sysnum));
- callstack_pop(event->proc);
- }
- continue_process(event->proc->pid);
+handle_sysret(Event *event)
+{
+ handle_x_sysret(event, &sysname);
+}
+
+static void
+handle_arch_sysret(Event *event)
+{
+ handle_x_sysret(event, &arch_sysname);
}
static void
output_right_tos(struct process *proc)
{
size_t d = proc->callstack_depth;
+ assert(d > 0);
struct callstack_element *elem = &proc->callstack[d - 1];
- if (proc->state != STATE_IGNORED)
- output_right(LT_TOF_FUNCTIONR, proc, elem->c_un.libfunc);
+ assert(! elem->is_syscall);
+
+ if (proc->state != STATE_IGNORED) {
+ struct timedelta spent = calc_time_spent(elem->enter_time);
+ if (options.summary)
+ summary_account_call(elem->c_un.libfunc, spent);
+ else
+ output_right(LT_TOF_FUNCTIONR, proc, elem->c_un.libfunc,
+ &spent);
+ }
}
#ifndef ARCH_HAVE_SYMBOL_RET
@@ -645,14 +693,8 @@ handle_breakpoint(Event *event)
for (i = event->proc->callstack_depth - 1; i >= 0; i--) {
if (brk_addr == event->proc->callstack[i].return_addr) {
- for (j = event->proc->callstack_depth - 1; j > i; j--) {
+ for (j = event->proc->callstack_depth - 1; j > i; j--)
callstack_pop(event->proc);
- }
- if (event->proc->state != STATE_IGNORED) {
- if (opt_T || options.summary) {
- calc_time_spent(event->proc);
- }
- }
struct library_symbol *libsym =
event->proc->callstack[i].c_un.libfunc;
@@ -705,11 +747,14 @@ handle_breakpoint(Event *event)
/* breakpoint_on_hit may delete its own breakpoint, so we have
* to look it up again. */
if ((sbp = address2bpstruct(leader, brk_addr)) != NULL) {
+
if (event->proc->state != STATE_IGNORED
&& sbp->libsym != NULL) {
event->proc->stack_pointer = get_stack_pointer(event->proc);
callstack_push_symfunc(event->proc, sbp);
- output_left(LT_TOF_FUNCTION, event->proc, sbp->libsym);
+ if (! options.summary)
+ output_left(LT_TOF_FUNCTION, event->proc,
+ sbp->libsym);
}
breakpoint_on_continue(sbp, event->proc);
@@ -743,7 +788,7 @@ callstack_push_syscall(struct process *proc, int sysnum)
proc->callstack_depth++;
if (opt_T || options.summary) {
struct timezone tz;
- gettimeofday(&elem->time_spent, &tz);
+ gettimeofday(&elem->enter_time, &tz);
}
}
@@ -781,7 +826,7 @@ callstack_push_symfunc(struct process *proc, struct breakpoint *bp)
if (opt_T || options.summary) {
struct timezone tz;
- gettimeofday(&elem->time_spent, &tz);
+ gettimeofday(&elem->enter_time, &tz);
}
}
diff --git a/libltrace.c b/libltrace.c
index 2d910a1..0112c9f 100644
--- a/libltrace.c
+++ b/libltrace.c
@@ -32,11 +32,12 @@
#include <string.h>
#include <unistd.h>
+#include "backend.h"
#include "common.h"
#include "proc.h"
-#include "read_config_file.h"
-#include "backend.h"
#include "prototype.h"
+#include "read_config_file.h"
+#include "summary.h"
char *command = NULL;
diff --git a/options.h b/options.h
index 6c28ed9..d0df3a7 100644
--- a/options.h
+++ b/options.h
@@ -1,6 +1,6 @@
/*
* This file is part of ltrace.
- * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2012,2013 Petr Machata, Red Hat Inc.
* Copyright (C) 2009,2010 Joe Damato
* Copyright (C) 1998,2002,2008 Juan Cespedes
* Copyright (C) 2006 Ian Wienand
@@ -103,12 +103,6 @@ int parse_colon_separated_list(const char *paths, struct vect *vec);
/* Vector of struct opt_F_t. */
extern struct vect opt_F;
-struct opt_c_struct {
- int count;
- struct timeval tv;
-};
-extern struct dict *dict_opt_c;
-
extern char **process_options(int argc, char **argv);
#endif /* _OPTIONS_H_ */
diff --git a/output.c b/output.c
index edf4522..82b6a5e 100644
--- a/output.c
+++ b/output.c
@@ -44,16 +44,12 @@
#include "param.h"
#include "proc.h"
#include "prototype.h"
+#include "summary.h"
#include "type.h"
#include "value.h"
#include "value_dict.h"
-/* TODO FIXME XXX: include in common.h: */
-extern struct timeval current_time_spent;
-
-struct dict *dict_opt_c = NULL;
-
-static struct process *current_proc = 0;
+static struct process *current_proc = NULL;
static size_t current_depth = 0;
static int current_column = 0;
@@ -498,9 +494,8 @@ void
output_left(enum tof type, struct process *proc,
struct library_symbol *libsym)
{
- if (options.summary) {
- return;
- }
+ assert(! options.summary);
+
if (current_proc) {
fprintf(options.output, " <unfinished ...>\n");
current_column = 0;
@@ -572,70 +567,21 @@ output_left(enum tof type, struct process *proc,
stel->out.need_delim = need_delim;
}
-static void
-free_stringp_cb(const char **stringp, void *data)
-{
- free((char *)*stringp);
-}
-
void
-output_right(enum tof type, struct process *proc, struct library_symbol *libsym)
+output_right(enum tof type, struct process *proc, struct library_symbol *libsym,
+ struct timedelta *spent)
{
+ assert(! options.summary);
+
struct prototype *func = lookup_symbol_prototype(proc, libsym);
if (func == NULL)
return;
-again:
- if (options.summary) {
- if (dict_opt_c == NULL) {
- dict_opt_c = malloc(sizeof(*dict_opt_c));
- if (dict_opt_c == NULL) {
- oom:
- fprintf(stderr,
- "Can't allocate memory for "
- "keeping track of -c.\n");
- free(dict_opt_c);
- options.summary = 0;
- goto again;
- }
- DICT_INIT(dict_opt_c, char *, struct opt_c_struct,
- dict_hash_string, dict_eq_string, NULL);
- }
-
- struct opt_c_struct *st
- = DICT_FIND_REF(dict_opt_c, &libsym->name,
- struct opt_c_struct);
- if (st == NULL) {
- const char *na = strdup(libsym->name);
- struct opt_c_struct new_st = {.count = 0, .tv = {0, 0}};
- if (na == NULL
- || DICT_INSERT(dict_opt_c, &na, &new_st) < 0) {
- free((char *)na);
- DICT_DESTROY(dict_opt_c, const char *,
- struct opt_c_struct,
- free_stringp_cb, NULL, NULL);
- goto oom;
- }
- st = DICT_FIND_REF(dict_opt_c, &libsym->name,
- struct opt_c_struct);
- assert(st != NULL);
- }
-
- if (st->tv.tv_usec + current_time_spent.tv_usec > 1000000) {
- st->tv.tv_usec += current_time_spent.tv_usec - 1000000;
- st->tv.tv_sec++;
- } else {
- st->tv.tv_usec += current_time_spent.tv_usec;
- }
- st->count++;
- st->tv.tv_sec += current_time_spent.tv_sec;
- return;
- }
-
- if (current_proc && (current_proc != proc ||
- current_depth != proc->callstack_depth)) {
+ if (current_proc != NULL
+ && (current_proc != proc
+ || current_depth != proc->callstack_depth)) {
fprintf(options.output, " <unfinished ...>\n");
- current_proc = 0;
+ current_proc = NULL;
}
if (current_proc != proc) {
begin_of_line(proc, type == LT_TOF_FUNCTIONR, 1);
@@ -689,10 +635,12 @@ again:
value_destroy(&retval);
if (opt_T) {
+ assert(spent != NULL);
fprintf(options.output, " <%lu.%06d>",
- (unsigned long)current_time_spent.tv_sec,
- (int)current_time_spent.tv_usec);
+ (unsigned long) spent->tm.tv_sec,
+ (int) spent->tm.tv_usec);
}
+
fprintf(options.output, "\n");
#if defined(HAVE_LIBUNWIND)
@@ -746,7 +694,7 @@ again:
}
#endif /* defined(HAVE_LIBUNWIND) */
- current_proc = 0;
+ current_proc = NULL;
current_column = 0;
}
diff --git a/output.h b/output.h
index b9f0518..2e74d61 100644
--- a/output.h
+++ b/output.h
@@ -1,6 +1,6 @@
/*
* This file is part of ltrace.
- * Copyright (C) 2011, 2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2011, 2012, 2013 Petr Machata, Red Hat Inc.
* Copyright (C) 2009 Juan Cespedes
*
* This program is free software; you can redistribute it and/or
@@ -28,7 +28,8 @@ void output_line(struct process *proc, const char *fmt, ...);
void output_left(enum tof type, struct process *proc,
struct library_symbol *libsym);
void output_right(enum tof type, struct process *proc,
- struct library_symbol *libsym);
+ struct library_symbol *libsym,
+ struct timedelta *spent);
/* This function is for emitting lists of comma-separated strings.
*
diff --git a/proc.h b/proc.h
index e8032fa..64f8fe2 100644
--- a/proc.h
+++ b/proc.h
@@ -66,7 +66,7 @@ struct callstack_element {
} c_un;
int is_syscall;
arch_addr_t return_addr;
- struct timeval time_spent;
+ struct timeval enter_time;
struct fetch_context *fetch_context;
struct value_dict *arguments;
struct output_state out;
diff --git a/summary.c b/summary.c
index 9e22086..9103f71 100644
--- a/summary.c
+++ b/summary.c
@@ -22,11 +22,15 @@
#include "config.h"
+#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
-#include <sys/time.h>
+#include <string.h>
-#include "common.h"
+#include "summary.h"
+#include "dict.h"
+#include "library.h"
+#include "options.h"
struct entry_st {
const char *name;
@@ -40,6 +44,32 @@ struct fill_struct_data {
unsigned long tot_usecs;
};
+struct opt_c_struct {
+ int count;
+ struct timeval tv;
+};
+
+static struct dict *dict_opt_c;
+
+struct timedelta
+calc_time_spent(struct timeval start)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ struct timeval diff;
+ diff.tv_sec = tv.tv_sec - start.tv_sec;
+ if (tv.tv_usec >= start.tv_usec) {
+ diff.tv_usec = tv.tv_usec - start.tv_usec;
+ } else {
+ diff.tv_sec--;
+ diff.tv_usec = 1000000 + tv.tv_usec - start.tv_usec;
+ }
+
+ struct timedelta ret = { diff };
+ return ret;
+}
+
static enum callback_status
fill_struct(const char **namep, struct opt_c_struct *st, void *u)
{
@@ -114,3 +144,58 @@ show_summary(void)
vect_destroy(&cdata.entries, NULL, NULL);
}
+
+static void
+free_stringp_cb(const char **stringp, void *data)
+{
+ free((char *)*stringp);
+}
+
+void
+summary_account_call(struct library_symbol *libsym, struct timedelta spent)
+{
+ assert(options.summary);
+
+ if (dict_opt_c == NULL) {
+ dict_opt_c = malloc(sizeof(*dict_opt_c));
+ if (dict_opt_c == NULL) {
+ oom:
+ fprintf(stderr,
+ "Can't allocate memory for "
+ "keeping track of -c.\n");
+ free(dict_opt_c);
+ options.summary = 0;
+ return;
+ }
+ DICT_INIT(dict_opt_c, char *, struct opt_c_struct,
+ dict_hash_string, dict_eq_string, NULL);
+ }
+
+ struct opt_c_struct *st = DICT_FIND_REF(dict_opt_c, &libsym->name,
+ struct opt_c_struct);
+ if (st == NULL) {
+ const char *na = strdup(libsym->name);
+ struct opt_c_struct new_st = {.count = 0, .tv = {0, 0}};
+ if (na == NULL
+ || DICT_INSERT(dict_opt_c, &na, &new_st) < 0) {
+ free((char *) na);
+ DICT_DESTROY(dict_opt_c, const char *,
+ struct opt_c_struct,
+ free_stringp_cb, NULL, NULL);
+ goto oom;
+ }
+ st = DICT_FIND_REF(dict_opt_c, &libsym->name,
+ struct opt_c_struct);
+ assert(st != NULL);
+ }
+
+ if (st->tv.tv_usec + spent.tm.tv_usec > 1000000) {
+ st->tv.tv_usec += spent.tm.tv_usec - 1000000;
+ st->tv.tv_sec++;
+ } else {
+ st->tv.tv_usec += spent.tm.tv_usec;
+ }
+ st->count++;
+ st->tv.tv_sec += spent.tm.tv_sec;
+ return;
+}
diff --git a/summary.h b/summary.h
new file mode 100644
index 0000000..f680ef9
--- /dev/null
+++ b/summary.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2013 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 _SUMMARY_H_
+#define _SUMMARY_H_
+
+#include "forward.h"
+
+struct timedelta {
+ struct timeval tm;
+};
+
+struct timedelta calc_time_spent(struct timeval start);
+void summary_account_call(struct library_symbol *libsym,
+ struct timedelta spent);
+void show_summary(void);
+
+#endif /* _SUMMARY_H_ */
diff --git a/testsuite/ltrace.minor/trace-exec.exp b/testsuite/ltrace.minor/trace-exec.exp
index 7a953de..57260f8 100644
--- a/testsuite/ltrace.minor/trace-exec.exp
+++ b/testsuite/ltrace.minor/trace-exec.exp
@@ -1,5 +1,5 @@
# This file is part of ltrace.
-# Copyright (C) 2012 Petr Machata, Red Hat Inc.
+# Copyright (C) 2012, 2013 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
@@ -16,22 +16,30 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
-ltraceMatch [ltraceRun -xmain -- [ltraceCompile {} [ltraceSource c {
+set bin1 [ltraceCompile {} [ltraceSource c {
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char ** argv) {
execl(argv[1], argv[1], NULL);
abort();
}
-}]] [ltraceCompile {} [ltraceSource c {
+}]]
+
+set bin2 [ltraceCompile {} [ltraceSource c {
#include <stdio.h>
int main(void) {
return puts("Hello, World.");
}
-}]]] {
+}]]
+
+ltraceMatch [ltraceRun -xmain -- $bin1 $bin2] {
{{^execl\(} == 1}
{{^puts\(.*\) .*= 14} == 1}
{{^main\(} == 2}
}
+ltraceMatch [ltraceRun -c -- $bin1 $bin2] {
+ {{exec} > 0}
+}
+
ltraceDone
--
1.7.6.5

View File

@ -0,0 +1,36 @@
diff -urp ltrace-0.7.91/libltrace.c master/libltrace.c
--- ltrace-0.7.91/libltrace.c 2014-01-14 16:31:37.696174464 +0100
+++ master/libltrace.c 2013-11-21 14:06:38.623701688 +0100
@@ -113,9 +117,13 @@ ltrace_init(int argc, char **argv) {
if (command) {
/* Check that the binary ABI is supported before
* calling execute_program. */
- struct ltelf lte;
- ltelf_init(&lte, command);
- ltelf_destroy(&lte);
+ {
+ struct ltelf lte;
+ if (ltelf_init(&lte, command) == 0)
+ ltelf_destroy(&lte);
+ else
+ exit(EXIT_FAILURE);
+ }
pid_t pid = execute_program(command, argv);
struct process *proc = open_program(command, pid);
diff -urp ltrace-0.7.91/ltrace-elf.c master/ltrace-elf.c
--- ltrace-0.7.91/ltrace-elf.c 2014-01-14 16:31:37.688174420 +0100
+++ master/ltrace-elf.c 2013-11-22 18:17:11.767721609 +0100
@@ -361,8 +361,11 @@ ltelf_init(struct ltelf *lte, const char
{
memset(lte, 0, sizeof *lte);
lte->fd = open(filename, O_RDONLY);
- if (lte->fd == -1)
+ if (lte->fd == -1) {
+ fprintf(stderr, "Can't open %s: %s\n", filename,
+ strerror(errno));
return 1;
+ }
elf_version(EV_CURRENT);

45
ltrace-0.7.91-man.patch Normal file
View File

@ -0,0 +1,45 @@
diff -up ltrace-0.7.91/options.c\~ ltrace-0.7.91/options.c
--- ltrace-0.7.91/options.c~ 2013-10-22 11:54:21.000000000 +0200
+++ ltrace-0.7.91/options.c 2014-01-13 15:38:51.362221740 +0100
@@ -128,6 +128,8 @@ usage_debug(void) {
"\n"
"Debugging options are mixed using bitwise-or.\n"
"Note that the meanings and values are subject to change.\n"
+ "Also note that these values are used inconsistently in ltrace, and the\n"
+ "only debuglevel that you can rely on is -D77 that will show everything.\n"
);
}
diff -up ltrace-0.7.91/ltrace.1\~ ltrace-0.7.91/ltrace.1
--- ltrace-0.7.91/ltrace.1~ 2013-10-23 17:44:13.000000000 +0200
+++ ltrace-0.7.91/ltrace.1 2014-01-13 15:51:24.236730677 +0100
@@ -1,5 +1,5 @@
.\" -*-nroff-*-
-.\" Copyright (c) 2012, 2013 Petr Machata, Red Hat Inc.
+.\" Copyright (c) 2012,2013,2014 Petr Machata, Red Hat Inc.
.\" Copyright (c) 1997-2005 Juan Cespedes <cespedes@debian.org>
.\"
.\" This program is free software; you can redistribute it and/or
@@ -118,9 +118,9 @@ Besides removing any initial underscore
this makes C++ function names readable.
.IP "\-D, \-\-debug \fRmask\fI"
Show debugging output of \fBltrace\fR itself. \fImask\fR is a number
-with internal meaning that's not really well defined at all.
-\fImask\fR of 77 shows all debug messages, which is what you usually
-need.
+describing which debug messages should be displayed. Use the option
+\-Dh to see what can be used, but note that currently the only
+reliable debugmask is 77, which shows all debug messages.
.IP "\-e \fIfilter"
A qualifying expression which modifies which library calls to trace.
The format of the filter expression is described in the section
@@ -156,7 +156,8 @@ dependency ordering. If you want to mak
library are actually called, use \fB-x @\fIlibrary_pattern\fR instead.
.IP \-L
When no -e option is given, don't assume the default action of
-\fB@MAIN\fR.
+\fB@MAIN\fR. In practice this means that library calls will not be
+traced.
.IP "\-n, \-\-indent \fInr"
Indent trace output by \fInr\fR spaces for each level of call
nesting. Using this option makes the program flow visualization easy

View File

@ -0,0 +1,175 @@
From 4724bd5a4a19db117a1d280b9d1a3508fd4e03fa Mon Sep 17 00:00:00 2001
From: Petr Machata <pmachata@redhat.com>
Date: Wed, 8 Apr 2015 07:11:52 -0400
Subject: [PATCH 1/2] Convert main-threaded test case to new style
---
testsuite/ltrace.main/Makefile.am | 4 +-
testsuite/ltrace.main/main-threaded.c | 30 ----------
testsuite/ltrace.main/main-threaded.exp | 103 ++++++++++++++++++++------------
3 files changed, 66 insertions(+), 71 deletions(-)
delete mode 100644 testsuite/ltrace.main/main-threaded.c
diff --git a/testsuite/ltrace.main/Makefile.am b/testsuite/ltrace.main/Makefile.am
index 23ab8ab..06ad613 100644
--- a/testsuite/ltrace.main/Makefile.am
+++ b/testsuite/ltrace.main/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 1992 - 2001, 2012, 2013 Free Software Foundation, Inc.
+# Copyright (C) 1992 - 2001, 2012, 2013, 2015 Free Software Foundation, 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
@@ -17,7 +17,7 @@
EXTRA_DIST = branch_func.c branch_func.exp filters.exp hello-vfork.c \
hello-vfork.exp main.c main.exp main-internal.exp main-lib.c \
- main-threaded.c main-threaded.exp main-vfork.c main-vfork.exp \
+ main-threaded.exp main-vfork.c main-vfork.exp \
parameters.c parameters.conf parameters.exp parameters-lib.c \
parameters2.exp parameters3.exp signals.c signals.exp \
system_calls.c system_calls.exp system_call_params.exp
diff --git a/testsuite/ltrace.main/main-threaded.c b/testsuite/ltrace.main/main-threaded.c
deleted file mode 100644
index 2992d1e..0000000
--- a/testsuite/ltrace.main/main-threaded.c
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <pthread.h>
-
-extern void print (char *);
-
-#define PRINT_LOOP 10
-
-void *
-th_main (void *arg)
-{
- int i;
- for (i=0; i<PRINT_LOOP; i++)
- print (arg);
-}
-
-int
-main ()
-{
- pthread_t thread1;
- pthread_t thread2;
- pthread_t thread3;
- pthread_create (&thread1, NULL, th_main, "aaa");
- pthread_create (&thread2, NULL, th_main, "bbb");
- pthread_create (&thread3, NULL, th_main, "ccc");
- pthread_join (thread1, NULL);
- pthread_join (thread2, NULL);
- pthread_join (thread3, NULL);
- return 0;
-}
-
diff --git a/testsuite/ltrace.main/main-threaded.exp b/testsuite/ltrace.main/main-threaded.exp
index 4d5f478..cead82d 100644
--- a/testsuite/ltrace.main/main-threaded.exp
+++ b/testsuite/ltrace.main/main-threaded.exp
@@ -1,39 +1,64 @@
-# This file was written by Yao Qi <qiyao@cn.ibm.com>.
+# This file is part of ltrace.
+# Copyright (C) 2011, 2015 Petr Machata, Red Hat Inc.
+# Copyright (C) 2006 Yao Qi <qiyao@cn.ibm.com>.
+#
+# 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 libprint [ltraceCompile libprint.so [ltraceSource c {
+ #include<stdio.h>
+
+ void
+ print(char* s)
+ {
+ printf("%s\n",s);
+ }
+}]]
+
+set bin [ltraceCompile {} $libprint -lpthread [ltraceSource c {
+ #include <pthread.h>
+
+ extern void print (char *);
+
+ #define PRINT_LOOP 10
+
+ void *
+ th_main (void *arg)
+ {
+ int i;
+ for (i=0; i<PRINT_LOOP; i++)
+ print (arg);
+ return NULL;
+ }
+
+ int
+ main (void)
+ {
+ pthread_t thread1;
+ pthread_t thread2;
+ pthread_t thread3;
+ pthread_create (&thread1, NULL, th_main, "aaa");
+ pthread_create (&thread2, NULL, th_main, "bbb");
+ pthread_create (&thread3, NULL, th_main, "ccc");
+ pthread_join (thread1, NULL);
+ pthread_join (thread2, NULL);
+ pthread_join (thread3, NULL);
+ return 0;
+ }
+}]]
-set testfile "main-threaded"
-set srcfile ${testfile}.c
-set binfile ${testfile}
-set libfile "main-lib"
-set libsrc $srcdir/$subdir/$libfile.c
-set lib_sl $objdir/$subdir/lib$testfile.so
-
-
-if [get_compiler_info $binfile] {
- return -1
-}
-
-verbose "compiling source file now....."
-if { [ltrace_compile_shlib $libsrc $lib_sl debug ] != ""
- || [ltrace_compile $srcdir/$subdir/$srcfile $objdir/$subdir/$binfile executable [list debug shlib=$lib_sl ldflags=-pthread] ] != ""} {
- send_user "Testcase compile failed, so all tests in this file will automatically fail.\n"
-}
-
-# set options for ltrace.
-ltrace_options "-l" "lib$testfile.so" "-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-threaded.ltrace.
-set pattern "print"
-ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 30
+ltraceMatch1 [ltraceRun -f -l libprint.so -- $bin] {print\(} == 30
+
+ltraceDone
Only in ltrace.main: main-threaded.exp~
Only in ltrace.main: .main-threaded.exp.~undo-tree~

View File

@ -0,0 +1,50 @@
From 72ee29639c55b5942bc07c8ed0013005f8fc5a97 Mon Sep 17 00:00:00 2001
From: Petr Machata <pmachata@redhat.com>
Date: Wed, 8 Apr 2015 07:14:10 -0400
Subject: [PATCH 2/2] Fix tracing multi-threaded processes without -f
- In handle_syscall, we avoid touching stack of ignored processes.
But in handle_sysret, we require a sysret-like stack entry even
for ignored processes, even though we then go ahead to not act
on that stack entry. Instead, for ignored processes, avoid looking
at stack trace at all.
---
handle_event.c | 10 +++++-----
testsuite/ltrace.main/main-threaded.exp | 1 +
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/handle_event.c b/handle_event.c
index 6fa7e98..c2550ad 100644
--- a/handle_event.c
+++ b/handle_event.c
@@ -619,12 +619,12 @@ handle_x_sysret(Event *event, char *(*name_cb)(struct process *, int))
debug(DEBUG_FUNCTION, "handle_x_sysret(pid=%d, sysnum=%d)",
event->proc->pid, event->e_un.sysnum);
- unsigned d = event->proc->callstack_depth;
- assert(d > 0);
- struct callstack_element *elem = &event->proc->callstack[d - 1];
- assert(elem->is_syscall);
-
if (event->proc->state != STATE_IGNORED) {
+ unsigned d = event->proc->callstack_depth;
+ assert(d > 0);
+ struct callstack_element *elem = &event->proc->callstack[d - 1];
+ assert(elem->is_syscall);
+
struct timedelta spent = calc_time_spent(elem->enter_time);
if (options.syscalls)
output_syscall_right(event->proc,
diff --git a/testsuite/ltrace.main/main-threaded.exp b/testsuite/ltrace.main/main-threaded.exp
index cead82d..aca7afd 100644
--- a/testsuite/ltrace.main/main-threaded.exp
+++ b/testsuite/ltrace.main/main-threaded.exp
@@ -60,5 +60,6 @@ set bin [ltraceCompile {} $libprint -lpthread [ltraceSource c {
}]]
ltraceMatch1 [ltraceRun -f -l libprint.so -- $bin] {print\(} == 30
+ltraceMatch1 [ltraceRun -L -- $bin] exited == 1
ltraceDone
--
2.1.0

View File

@ -0,0 +1,144 @@
From 2e9f9f1f5d0fb223b109429b9c904504b7f638e2 Mon Sep 17 00:00:00 2001
From: Petr Machata <pmachata@redhat.com>
Date: Fri, 8 Aug 2014 16:53:41 +0200
Subject: [PATCH] In config files, allow whitespace between identifier and
opening paren
---
read_config_file.c | 61 ++++++--------------------------
testsuite/ltrace.main/parameters2.exp | 14 +++++++-
2 files changed, 25 insertions(+), 50 deletions(-)
diff --git a/read_config_file.c b/read_config_file.c
index ea3ab88..05ff283 100644
--- a/read_config_file.c
+++ b/read_config_file.c
@@ -1,6 +1,6 @@
/*
* This file is part of ltrace.
- * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2011,2012,2013,2014 Petr Machata, Red Hat Inc.
* Copyright (C) 1998,1999,2003,2007,2008,2009 Juan Cespedes
* Copyright (C) 2006 Ian Wienand
* Copyright (C) 2006 Steve Fink
@@ -168,38 +168,6 @@ parse_ident(struct locus *loc, char **str)
return xstrndup(ident, *str - ident);
}
-/*
- Returns position in string at the left parenthesis which starts the
- function's argument signature. Returns NULL on error.
-*/
-static char *
-start_of_arg_sig(char *str) {
- char *pos;
- int stacked = 0;
-
- if (!strlen(str))
- return NULL;
-
- pos = &str[strlen(str)];
- do {
- pos--;
- if (pos < str)
- return NULL;
- while ((pos > str) && (*pos != ')') && (*pos != '('))
- pos--;
-
- if (*pos == ')')
- stacked++;
- else if (*pos == '(')
- stacked--;
- else
- return NULL;
-
- } while (stacked > 0);
-
- return (stacked == 0) ? pos : NULL;
-}
-
static int
parse_int(struct locus *loc, char **str, long *ret)
{
@@ -1110,7 +1078,6 @@ static int
process_line(struct protolib *plib, struct locus *loc, char *buf)
{
char *str = buf;
- char *tmp;
debug(3, "Reading line %d of `%s'", loc->line_no, loc->filename);
eat_spaces(&str);
@@ -1148,22 +1115,13 @@ process_line(struct protolib *plib, struct locus *loc, char *buf)
debug(4, " return_type = %d", fun.return_info->type);
eat_spaces(&str);
- tmp = start_of_arg_sig(str);
- if (tmp == NULL) {
- report_error(loc->filename, loc->line_no, "syntax error");
+ proto_name = parse_ident(loc, &str);
+ if (proto_name == NULL)
goto err;
- }
- *tmp = '\0';
- proto_name = strdup(str);
- if (proto_name == NULL) {
- oom:
- report_error(loc->filename, loc->line_no,
- "%s", strerror(errno));
+ eat_spaces(&str);
+ if (parse_char(loc, &str, '(') < 0)
goto err;
- }
-
- str = tmp + 1;
debug(3, " name = %s", proto_name);
struct param *extra_param = NULL;
@@ -1177,8 +1135,13 @@ process_line(struct protolib *plib, struct locus *loc, char *buf)
if (have_stop == 0) {
struct param param;
param_init_stop(&param);
- if (prototype_push_param(&fun, &param) < 0)
- goto oom;
+ if (prototype_push_param(&fun, &param) < 0) {
+ oom:
+ report_error(loc->filename,
+ loc->line_no,
+ "%s", strerror(errno));
+ goto err;
+ }
have_stop = 1;
}
str++;
diff --git a/testsuite/ltrace.main/parameters2.exp b/testsuite/ltrace.main/parameters2.exp
index 6318fc5..9850079 100644
--- a/testsuite/ltrace.main/parameters2.exp
+++ b/testsuite/ltrace.main/parameters2.exp
@@ -1,5 +1,5 @@
# This file is part of ltrace.
-# Copyright (C) 2012, 2013 Petr Machata, Red Hat Inc.
+# Copyright (C) 2012, 2013, 2014 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
@@ -259,4 +259,16 @@ ltraceMatch1 [ltraceLibTest {
somefunc();
}] {somefunc\(\) *= nil} == 1
+# Test that spaces in function name make no difference.
+
+ltraceMatch1 [ltraceLibTest {
+ void somefunc ();
+} {
+ void somefunc(void);
+} {
+ void somefunc(void) {}
+} {
+ somefunc();
+}] {somefunc\(\)} == 1
+
ltraceDone
--
1.7.6.5

View File

@ -0,0 +1,96 @@
diff -r -U3 -p ltrace-0.7.91.orig/filter.c ltrace-0.7.91.dj/filter.c
--- ltrace-0.7.91.orig/filter.c 2012-12-16 20:53:44.000000000 -0500
+++ ltrace-0.7.91.dj/filter.c 2016-06-17 19:07:23.678490985 -0400
@@ -79,7 +79,7 @@ filter_lib_matcher_name_init(struct filt
{
switch (type) {
case FLM_MAIN:
- assert(type != type);
+ //assert(type != type);
abort();
case FLM_SONAME:
@@ -137,7 +137,7 @@ matcher_matches_library(struct filter_li
case FLM_MAIN:
return lib->type == LT_LIBTYPE_MAIN;
}
- assert(matcher->type != matcher->type);
+ //assert(matcher->type != matcher->type);
abort();
}
Only in ltrace-0.7.91.dj/: filter.c~
diff -r -U3 -p ltrace-0.7.91.orig/sysdeps/linux-gnu/proc.c ltrace-0.7.91.dj/sysdeps/linux-gnu/proc.c
--- ltrace-0.7.91.orig/sysdeps/linux-gnu/proc.c 2013-10-11 15:27:11.000000000 -0400
+++ ltrace-0.7.91.dj/sysdeps/linux-gnu/proc.c 2016-06-17 18:59:42.333774042 -0400
@@ -242,9 +242,10 @@ process_tasks(pid_t pid, pid_t **ret_tas
size_t alloc = 0;
while (1) {
- struct dirent entry;
struct dirent *result;
- if (readdir_r(d, &entry, &result) != 0) {
+ errno = 0;
+ result = readdir(d);
+ if (result == NULL && errno != 0) {
fail:
free(tasks);
closedir(d);
Only in ltrace-0.7.91.dj/sysdeps/linux-gnu: proc.c~
diff -r -U3 -p ltrace-0.7.91.orig/sysdeps/linux-gnu/x86/fetch.c ltrace-0.7.91.dj/sysdeps/linux-gnu/x86/fetch.c
--- ltrace-0.7.91.orig/sysdeps/linux-gnu/x86/fetch.c 2013-10-24 08:33:35.000000000 -0400
+++ ltrace-0.7.91.dj/sysdeps/linux-gnu/x86/fetch.c 2016-06-17 18:52:33.962842191 -0400
@@ -523,7 +523,7 @@ classify(struct process *proc, struct fe
default:
/* Unsupported type. */
- assert(info->type != info->type);
+ //assert(info->type != info->type);
abort();
}
abort();
Only in ltrace-0.7.91.dj/sysdeps/linux-gnu/x86: fetch.c~
diff -r -U3 -p ltrace-0.7.91.orig/sysdeps/linux-gnu/x86/trace.c ltrace-0.7.91.dj/sysdeps/linux-gnu/x86/trace.c
--- ltrace-0.7.91.orig/sysdeps/linux-gnu/x86/trace.c 2012-12-16 20:53:45.000000000 -0500
+++ ltrace-0.7.91.dj/sysdeps/linux-gnu/x86/trace.c 2016-06-17 18:52:16.699844065 -0400
@@ -145,7 +145,7 @@ arch_type_sizeof(struct process *proc, s
return (size_t)-2;
default:
- assert(info->type != info->type);
+ //assert(info->type != info->type);
abort();
}
}
@@ -158,7 +158,7 @@ arch_type_alignof(struct process *proc,
switch (info->type) {
default:
- assert(info->type != info->type);
+ //assert(info->type != info->type);
abort();
break;
Only in ltrace-0.7.91.dj/sysdeps/linux-gnu/x86: trace.c~
diff -r -U3 -p ltrace-0.7.91.orig/value.c ltrace-0.7.91.dj/value.c
--- ltrace-0.7.91.orig/value.c 2013-10-10 08:43:55.000000000 -0400
+++ ltrace-0.7.91.dj/value.c 2016-06-17 19:11:43.441047589 -0400
@@ -363,7 +363,7 @@ value_set_word(struct value *value, long
u.u64 = word;
break;
default:
- assert(sz != sz);
+ //assert(sz != sz);
abort();
}
@@ -414,7 +414,7 @@ value_extract_word(struct value *value,
*retp = (long)u.u64;
return 0;
default:
- assert(sz != sz);
+ //assert(sz != sz);
abort();
}
}
Only in ltrace-0.7.91.dj/: value.c~

View File

@ -0,0 +1,48 @@
From 57dbe34ea7aa54b97e11406e1cfb2e427a68779e Mon Sep 17 00:00:00 2001
From: Petr Machata <pmachata@redhat.com>
Date: Wed, 8 Apr 2015 16:04:13 +0200
Subject: [PATCH] Fix warnings in compilation of test-suite cases
---
testsuite/ltrace.main/signals.c | 5 +++--
testsuite/ltrace.minor/wchar.exp | 3 ++-
testsuite/ltrace.torture/signals.c | 5 +++--
3 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/testsuite/ltrace.main/signals.c b/testsuite/ltrace.main/signals.c
index a02e795..ab23fc7 100644
--- a/testsuite/ltrace.main/signals.c
+++ b/testsuite/ltrace.main/signals.c
@@ -2,9 +2,10 @@
Objectives : Verify that ltrace can trace user defined signal.
This file was written by Yao Qi <qiyao@cn.ibm.com>. */
-#include<stdio.h>
-#include<signal.h>
+#include <stdio.h>
+#include <signal.h>
#include <sys/types.h>
+#include <unistd.h>
#define LOOP 7
diff --git a/testsuite/ltrace.torture/signals.c b/testsuite/ltrace.torture/signals.c
index b786c81..c66416e 100644
--- a/testsuite/ltrace.torture/signals.c
+++ b/testsuite/ltrace.torture/signals.c
@@ -2,9 +2,10 @@
Objectives : Verify that ltrace can trace user defined signal.
This file was written by Yao Qi <qiyao@cn.ibm.com>. */
-#include<stdio.h>
-#include<signal.h>
+#include <stdio.h>
+#include <signal.h>
#include <sys/types.h>
+#include <unistd.h>
#define LOOP 20
--
2.3.5

View File

@ -0,0 +1,216 @@
From 694d19ff14017926454771cbb63a22355b72f1bf Mon Sep 17 00:00:00 2001
From: Faraz Shahbazker <faraz.shahbazker@imgtec.com>
Date: Tue, 3 Feb 2015 13:07:55 -0800
Subject: [PATCH] Fix missing includes and return statements in test sources
Fix warnings while compiling test cases by adding missing #includes and
return statements. Missing arguments provided for functions wait()/wcswidth()
---
testsuite/ltrace.main/filters.exp | 1 +
testsuite/ltrace.main/main-internal.exp | 4 +++-
testsuite/ltrace.main/main-threaded.c | 1 +
testsuite/ltrace.main/parameters.c | 1 +
testsuite/ltrace.main/parameters2.exp | 2 +-
testsuite/ltrace.main/parameters3.exp | 2 ++
testsuite/ltrace.main/system_call_params.exp | 4 ++++
testsuite/ltrace.minor/attach-process.exp | 1 +
testsuite/ltrace.minor/libdl-simple.c | 2 ++
testsuite/ltrace.minor/time-record.c | 1 +
testsuite/ltrace.minor/trace-clone.c | 2 ++
testsuite/ltrace.minor/trace-fork.c | 4 +++-
testsuite/ltrace.minor/wchar.exp | 3 ++-
testsuite/ltrace.torture/vfork-thread.c | 1 +
14 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/testsuite/ltrace.main/filters.exp b/testsuite/ltrace.main/filters.exp
index 988346f..f7f4140 100644
--- a/testsuite/ltrace.main/filters.exp
+++ b/testsuite/ltrace.main/filters.exp
@@ -22,6 +22,7 @@ set libfilt1 [ltraceCompile libfilt1.so [ltraceSource c {
}]]
set libfilt2 [ltraceCompile libfilt2.so [ltraceSource c {
+ #include <stdio.h>
void func2(void) { puts("func2"); }
}]]
diff --git a/testsuite/ltrace.main/main-internal.exp b/testsuite/ltrace.main/main-internal.exp
index 0ca5e14..112c69b 100644
--- a/testsuite/ltrace.main/main-internal.exp
+++ b/testsuite/ltrace.main/main-internal.exp
@@ -19,11 +19,13 @@
set bin [ltraceCompile {} [ltraceSource c {
__attribute__((noinline)) void this(void) {}
__attribute__((noinline)) void that(void) {}
- int main(int i) {
+ int main() {
+ int i;
for (i = 0; i < 12; ++i) {
this();
that();
}
+ return 0;
}
}]]
diff --git a/testsuite/ltrace.main/parameters.c b/testsuite/ltrace.main/parameters.c
index a3d8bb5..aa862b9 100644
--- a/testsuite/ltrace.main/parameters.c
+++ b/testsuite/ltrace.main/parameters.c
@@ -17,6 +17,7 @@ void func_intptr_ret(int *i);
int func_strlen(char*);
void func_strfixed(char*);
void func_ppp(int***);
+void func_string(char*);
void func_stringp(char**);
void func_short(short, short);
void func_ushort(unsigned short, unsigned short);
diff --git a/testsuite/ltrace.main/parameters2.exp b/testsuite/ltrace.main/parameters2.exp
index 9850079..1c7b3b4 100644
--- a/testsuite/ltrace.main/parameters2.exp
+++ b/testsuite/ltrace.main/parameters2.exp
@@ -17,7 +17,7 @@
# 02110-1301 USA
set trivial [ltraceCompile {} [ltraceSource c {
- int main(void) {}
+ int main(void) {return 0;}
}]]
ltraceMatch1 [ltraceRun -L -F [ltraceSource conf {
diff --git a/testsuite/ltrace.main/parameters3.exp b/testsuite/ltrace.main/parameters3.exp
index 693c219..f6d9116 100644
--- a/testsuite/ltrace.main/parameters3.exp
+++ b/testsuite/ltrace.main/parameters3.exp
@@ -29,8 +29,10 @@ set liba [ltraceCompile liba.so [ltraceSource c {
}]]
set bin [ltraceCompile {} $liba [ltraceSource c {
+ extern void fun(void);
int main(void) {
fun();
+ return 0;
}
}]]
diff --git a/testsuite/ltrace.main/system_call_params.exp b/testsuite/ltrace.main/system_call_params.exp
index 2ccf840..f3a55d2 100644
--- a/testsuite/ltrace.main/system_call_params.exp
+++ b/testsuite/ltrace.main/system_call_params.exp
@@ -17,12 +17,15 @@
# 02110-1301 USA
set bin [ltraceCompile {} [ltraceSource c {
+ #ifndef _GNU_SOURCE
#define _GNU_SOURCE
+ #endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/syscall.h> /* For SYS_xxx definitions */
+ #include <sys/mount.h>
#ifndef SYS_open
# if defined(__aarch64__)
@@ -38,6 +41,7 @@ set bin [ltraceCompile {} [ltraceSource c {
syscall(SYS_open, "/some/path", O_RDONLY);
write(1, "something", 10);
mount("source", "target", "filesystemtype", 0, 0);
+ return 0;
}
}]]
diff --git a/testsuite/ltrace.minor/attach-process.exp b/testsuite/ltrace.minor/attach-process.exp
index 2c7d20c..c050f21 100644
--- a/testsuite/ltrace.minor/attach-process.exp
+++ b/testsuite/ltrace.minor/attach-process.exp
@@ -21,6 +21,7 @@ set bin [ltraceCompile {} [ltraceSource c {
int main(void) {
sleep(5);
sleep(1);
+ return 0;
}
}]]
diff --git a/testsuite/ltrace.minor/libdl-simple.c b/testsuite/ltrace.minor/libdl-simple.c
index 0bef5cf..b1be002 100644
--- a/testsuite/ltrace.minor/libdl-simple.c
+++ b/testsuite/ltrace.minor/libdl-simple.c
@@ -1,6 +1,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
+#include <string.h>
int main(int argc, char **argv) {
void *handle;
@@ -21,4 +22,5 @@ int main(int argc, char **argv) {
printf("%d\n", test(5));
dlclose(handle);
+ return 0;
}
diff --git a/testsuite/ltrace.minor/time-record.c b/testsuite/ltrace.minor/time-record.c
index a66b838..7d5e5e3 100644
--- a/testsuite/ltrace.minor/time-record.c
+++ b/testsuite/ltrace.minor/time-record.c
@@ -5,6 +5,7 @@
This file was written by Yao Qi <qiyao@cn.ibm.com>. */
#include <stdio.h>
#include <time.h>
+#include <unistd.h>
#define SLEEP_COUNT 2
#define NANOSLEEP_COUNT 50
diff --git a/testsuite/ltrace.minor/trace-clone.c b/testsuite/ltrace.minor/trace-clone.c
index ded930c..6aab235 100644
--- a/testsuite/ltrace.minor/trace-clone.c
+++ b/testsuite/ltrace.minor/trace-clone.c
@@ -3,7 +3,9 @@
clone called.
This file was written by Yao Qi <qiyao@cn.ibm.com>. */
+#ifndef _GNU_SOURCE
#define _GNU_SOURCE
+#endif
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
diff --git a/testsuite/ltrace.minor/trace-fork.c b/testsuite/ltrace.minor/trace-fork.c
index c5f0c71..9611184 100644
--- a/testsuite/ltrace.minor/trace-fork.c
+++ b/testsuite/ltrace.minor/trace-fork.c
@@ -6,6 +6,8 @@
#include <stdio.h>
#include <sys/types.h>
+#include <unistd.h>
+#include <sys/wait.h>
void
child ()
@@ -27,7 +29,7 @@ main ()
else
{
printf("My child pid is %d\n",pid);
- wait();
+ wait(NULL);
}
return 0;
}
diff --git a/testsuite/ltrace.torture/vfork-thread.c b/testsuite/ltrace.torture/vfork-thread.c
index f909bd3..4c118a6 100644
--- a/testsuite/ltrace.torture/vfork-thread.c
+++ b/testsuite/ltrace.torture/vfork-thread.c
@@ -13,6 +13,7 @@ routine (void *data)
puts ("bleble");
sleep (1);
}
+ return NULL;
}
--
2.1.0

View File

@ -0,0 +1,422 @@
Common subdirectories: ltrace-0.7.91/config and ltrace-0.7.91-pm/config
diff -u ltrace-0.7.91/configure.ac ltrace-0.7.91-pm/configure.ac
--- ltrace-0.7.91/configure.ac 2015-01-09 00:38:17.977190726 +0100
+++ ltrace-0.7.91-pm/configure.ac 2015-01-09 00:37:40.261910548 +0100
@@ -128,6 +128,51 @@
AC_CHECK_HEADERS(selinux/selinux.h)
AC_CHECK_LIB(selinux, security_get_boolean_active)
+dnl Whether (and which) elfutils libdw.so to use for unwinding.
+AC_ARG_WITH(elfutils,
+ AS_HELP_STRING([--with-elfutils], [Use elfutils libdwfl unwinding support]),
+ [case "${withval}" in
+ (yes|no) enable_elfutils=$withval;;
+ (*) enable_elfutils=yes
+ AM_CPPFLAGS="${AM_CPPFLAGS} -I${withval}/include"
+ AM_LDFLAGS="${AM_LDFLAGS} -L${withval}/lib"
+ elfutils_LD_LIBRARY_PATH="${withval}/lib:${withval}/lib/elfutils"
+ ;;
+esac],[enable_elfutils=maybe])
+
+dnl Check whether we have the elfutils libdwfl.h header installed.
+saved_CPPFLAGS="${CPPFLAGS}"
+CPPFLAGS="${CPPFLAGS} ${AM_CPPFLAGS}"
+AC_CHECK_HEADERS([elfutils/libdwfl.h],[have_libdwfl_h=yes])
+CPPFLAGS="${saved_CPPFLAGS}"
+
+dnl And whether libdw.so provides the unwinding functions.
+saved_LDFLAGS="${LDFLAGS}"
+LDFLAGS="${LDFLAGS} ${AM_LDFLAGS}"
+AC_CHECK_LIB([dw], [dwfl_getthread_frames], [have_libdw_dwfl_frames=yes])
+LDFLAGS="${saved_LDFLAGS}"
+
+AC_MSG_CHECKING([whether to use elfutils libdwfl unwinding support])
+case "${enable_elfutils}" in
+(yes|maybe)
+ if test x$have_libdwfl_h = xyes -a x$have_libdw_dwfl_frames = xyes; then
+ enable_elfutils=yes
+ elif test $enable_elfutils = maybe; then
+ enable_elfutils=no
+ else
+ AC_MSG_RESULT([$enable_elfutils])
+ AC_MSG_ERROR([Missing elfutils/libdwfl.h or dwfl_getthread_frames not in libdw.so])
+ fi
+ ;;
+(*) ;;
+esac
+AC_MSG_RESULT([$enable_elfutils])
+
+if test x"$enable_elfutils" = xyes; then
+ libdw_LIBS=-ldw
+ AC_SUBST(libdw_LIBS)
+ AC_DEFINE([HAVE_LIBDW], [1], [we have elfutils libdw])
+fi
# HAVE_LIBUNWIND
AC_ARG_WITH(libunwind,
@@ -193,6 +238,13 @@
LDFLAGS="${saved_LDFLAGS}"
fi
+if test x"$enable_elfutils" = xyes -a x"$enable_libunwind" = xyes; then
+ AC_MSG_ERROR([Cannot enable both --with-libunwind and --with-elfutils])
+fi
+
+if test x"$enable_elfutils" = xyes -o x"$enable_libunwind" = xyes; then
+ AC_DEFINE([HAVE_UNWINDER], [1], [we have an unwinder available])
+fi
saved_CPPFLAGS="${CPPFLAGS}"
saved_LDFLAGS="${LDFLAGS}"
@@ -340,6 +392,7 @@
AC_SUBST(AM_CFLAGS)
AC_SUBST(AM_LDFLAGS)
AC_SUBST(libelf_LD_LIBRARY_PATH)
+AC_SUBST(elfutils_LD_LIBRARY_PATH)
AC_SUBST(libunwind_LD_LIBRARY_PATH)
AC_CONFIG_FILES([
Common subdirectories: ltrace-0.7.91/debian and ltrace-0.7.91-pm/debian
Common subdirectories: ltrace-0.7.91/etc and ltrace-0.7.91-pm/etc
diff -u ltrace-0.7.91/ltrace.1 ltrace-0.7.91-pm/ltrace.1
--- ltrace-0.7.91/ltrace.1 2015-01-09 00:38:17.975190764 +0100
+++ ltrace-0.7.91-pm/ltrace.1 2015-01-09 00:37:40.261910548 +0100
@@ -196,7 +196,8 @@
correct execution of setuid and/or setgid binaries.
.IP "\-w, --where \fInr"
Show backtrace of \fInr\fR stack frames for each traced function. This
-option enabled only if libunwind support was enabled at compile time.
+option enabled only if elfutils or libunwind support was enabled at compile
+time.
.IP "\-x \fIfilter"
A qualifying expression which modifies which symbol table entry points
to trace. The format of the filter expression is described in the
Only in ltrace-0.7.91-pm/: ltrace.1.orig
diff -u ltrace-0.7.91/Makefile.am ltrace-0.7.91-pm/Makefile.am
--- ltrace-0.7.91/Makefile.am 2015-01-09 00:38:17.965190955 +0100
+++ ltrace-0.7.91-pm/Makefile.am 2015-01-09 00:37:40.260910568 +0100
@@ -40,6 +40,7 @@
$(liberty_LIBS) \
$(libsupcxx_LIBS) \
$(libstdcxx_LIBS) \
+ $(libdw_LIBS) \
$(libunwind_LIBS) \
sysdeps/libos.la
diff -u ltrace-0.7.91/options.c ltrace-0.7.91-pm/options.c
--- ltrace-0.7.91/options.c 2015-01-09 00:38:17.974190783 +0100
+++ ltrace-0.7.91-pm/options.c 2015-01-09 00:37:40.261910548 +0100
@@ -107,9 +107,9 @@
" -T show the time spent inside each call.\n"
" -u USERNAME run command with the userid, groupid of username.\n"
" -V, --version output version information and exit.\n"
-#if defined(HAVE_LIBUNWIND)
+#if defined(HAVE_UNWINDER)
" -w, --where=NR print backtrace showing NR stack frames at most.\n"
-#endif /* defined(HAVE_LIBUNWIND) */
+#endif /* defined(HAVE_UNWINDER) */
" -x FILTER modify which static functions to trace.\n"
"\nReport bugs to ltrace-devel@lists.alioth.debian.org\n",
progname);
@@ -519,9 +519,9 @@
progname = argv[0];
options.output = stderr;
options.no_signals = 0;
-#if defined(HAVE_LIBUNWIND)
+#if defined(HAVE_UNWINDER)
options.bt_depth = -1;
-#endif /* defined(HAVE_LIBUNWIND) */
+#endif /* defined(HAVE_UNWINDER) */
guess_cols();
@@ -545,9 +545,9 @@
{"output", 1, 0, 'o'},
{"version", 0, 0, 'V'},
{"no-signals", 0, 0, 'b'},
-# if defined(HAVE_LIBUNWIND)
+# if defined(HAVE_UNWINDER)
{"where", 1, 0, 'w'},
-# endif /* defined(HAVE_LIBUNWIND) */
+# endif /* defined(HAVE_UNWINDER) */
{0, 0, 0, 0}
};
#endif
@@ -556,7 +556,7 @@
#ifdef USE_DEMANGLE
"C"
#endif
-#if defined(HAVE_LIBUNWIND)
+#if defined(HAVE_UNWINDER)
"w:"
#endif
"cfhiLrStTVba:A:D:e:F:l:n:o:p:s:u:x:X:";
@@ -681,11 +681,11 @@
"There is NO WARRANTY, to the extent permitted by law.\n");
exit(0);
break;
-#if defined(HAVE_LIBUNWIND)
+#if defined(HAVE_UNWINDER)
case 'w':
options.bt_depth = parse_int(optarg, 'w', 1, 0);
break;
-#endif /* defined(HAVE_LIBUNWIND) */
+#endif /* defined(HAVE_UNWINDER) */
case 'x':
parse_filter_chain(optarg, &options.static_filter);
Only in ltrace-0.7.91-pm/: options.c.orig
diff -u ltrace-0.7.91/options.h ltrace-0.7.91-pm/options.h
--- ltrace-0.7.91/options.h 2015-01-09 00:38:17.966190936 +0100
+++ ltrace-0.7.91-pm/options.h 2015-01-09 00:37:40.261910548 +0100
@@ -44,9 +44,9 @@
size_t strlen; /* default maximum # of bytes printed in strings */
int follow; /* trace child processes */
int no_signals; /* don't print signals */
-#if defined(HAVE_LIBUNWIND)
+#if defined(HAVE_UNWINDER)
int bt_depth; /* how may levels of stack frames to show */
-#endif /* defined(HAVE_LIBUNWIND) */
+#endif /* defined(HAVE_UNWINDER) */
struct filter *plt_filter;
struct filter *static_filter;
diff -u ltrace-0.7.91/output.c ltrace-0.7.91-pm/output.c
--- ltrace-0.7.91/output.c 2015-01-09 00:38:17.966190936 +0100
+++ ltrace-0.7.91-pm/output.c 2015-01-09 00:37:40.261910548 +0100
@@ -33,6 +33,7 @@
#include <unistd.h>
#include <errno.h>
#include <assert.h>
+#include <inttypes.h>
#include "output.h"
#include "demangle.h"
@@ -567,6 +568,73 @@
stel->out.need_delim = need_delim;
}
+#if defined(HAVE_LIBDW)
+/* Prints information about one frame of a thread. Called by
+ dwfl_getthread_frames in output_right. Returns 1 when done (max
+ number of frames reached). Returns -1 on error. Returns 0 on
+ success (if there are more frames in the thread, call us again). */
+static int
+frame_callback (Dwfl_Frame *state, void *arg)
+{
+ Dwarf_Addr pc;
+ bool isactivation;
+
+ int *frames = (int *) arg;
+
+ if (!dwfl_frame_pc(state, &pc, &isactivation))
+ return -1;
+
+ if (!isactivation)
+ pc--;
+
+ Dwfl *dwfl = dwfl_thread_dwfl(dwfl_frame_thread(state));
+ Dwfl_Module *mod = dwfl_addrmodule(dwfl, pc);
+ const char *modname = NULL;
+ const char *symname = NULL;
+ GElf_Off off = 0;
+ if (mod != NULL) {
+ GElf_Sym sym;
+ modname = dwfl_module_info(mod, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ symname = dwfl_module_addrinfo(mod, pc, &off, &sym,
+ NULL, NULL, NULL);
+ }
+
+ /* This mimics the output produced by libunwind below. */
+ fprintf(options.output, " > %s(%s+0x%" PRIx64 ") [%" PRIx64 "]\n",
+ modname, symname, off, pc);
+
+ /* See if we can extract the source line too and print it on
+ the next line if we can find it. */
+ if (mod != NULL) {
+ Dwfl_Line *l = dwfl_module_getsrc(mod, pc);
+ if (l != NULL) {
+ int line, col;
+ line = col = -1;
+ const char *src = dwfl_lineinfo(l, NULL, &line, &col,
+ NULL, NULL);
+ if (src != NULL) {
+ fprintf(options.output, "\t%s", src);
+ if (line > 0) {
+ fprintf(options.output, ":%d", line);
+ if (col > 0)
+ fprintf(options.output,
+ ":%d", col);
+ }
+ fprintf(options.output, "\n");
+ }
+
+ }
+ }
+
+ /* Max number of frames to print reached? */
+ if ((*frames)-- == 0)
+ return 1;
+
+ return 0;
+}
+#endif /* defined(HAVE_LIBDW) */
+
void
output_right(enum tof type, struct process *proc, struct library_symbol *libsym,
struct timedelta *spent)
@@ -694,6 +762,24 @@
}
#endif /* defined(HAVE_LIBUNWIND) */
+#if defined(HAVE_LIBDW)
+ if (options.bt_depth > 0 && proc->leader->dwfl != NULL) {
+ int frames = options.bt_depth;
+ if (dwfl_getthread_frames(proc->leader->dwfl, proc->pid,
+ frame_callback, &frames) < 0) {
+ // Only print an error if we couldn't show anything.
+ // Otherwise just show there might be more...
+ if (frames == options.bt_depth)
+ fprintf(stderr,
+ "dwfl_getthread_frames tid %d: %s\n",
+ proc->pid, dwfl_errmsg(-1));
+ else
+ fprintf(options.output, " > [...]\n");
+ }
+ fprintf(options.output, "\n");
+ }
+#endif /* defined(HAVE_LIBDW) */
+
current_proc = NULL;
current_column = 0;
}
Only in ltrace-0.7.91-pm/: output.c.orig
diff -u ltrace-0.7.91/proc.c ltrace-0.7.91-pm/proc.c
--- ltrace-0.7.91/proc.c 2015-01-09 00:38:17.981190650 +0100
+++ ltrace-0.7.91-pm/proc.c 2015-01-09 00:37:40.261910548 +0100
@@ -111,6 +111,11 @@
if (proc->unwind_as != NULL)
unw_destroy_addr_space(proc->unwind_as);
#endif /* defined(HAVE_LIBUNWIND) */
+
+#if defined(HAVE_LIBDW)
+ if (proc->dwfl != NULL)
+ dwfl_end(proc->dwfl);
+#endif /* defined(HAVE_LIBDW) */
}
static int
@@ -172,6 +177,10 @@
}
#endif /* defined(HAVE_LIBUNWIND) */
+#if defined(HAVE_LIBDW)
+ proc->dwfl = NULL; /* Initialize for leader only on first library. */
+#endif /* defined(HAVE_LIBDW) */
+
return 0;
}
@@ -887,6 +896,59 @@
debug(DEBUG_PROCESS, "added library %s@%p (%s) to %d",
lib->soname, lib->base, lib->pathname, proc->pid);
+#if defined(HAVE_LIBDW)
+ if (options.bt_depth > 0) {
+ /* Setup module tracking for libdwfl unwinding. */
+ struct process *leader = proc->leader;
+ Dwfl *dwfl = leader->dwfl;
+ if (dwfl == NULL) {
+ static const Dwfl_Callbacks proc_callbacks = {
+ .find_elf = dwfl_linux_proc_find_elf,
+ .find_debuginfo = dwfl_standard_find_debuginfo
+ };
+ dwfl = dwfl_begin(&proc_callbacks);
+ if (dwfl == NULL)
+ fprintf(stderr,
+ "Couldn't initialize libdwfl unwinding "
+ "for process %d: %s\n", leader->pid,
+ dwfl_errmsg (-1));
+ }
+
+ if (dwfl != NULL) {
+ dwfl_report_begin_add(dwfl);
+ if (dwfl_report_elf(dwfl, lib->soname,
+ lib->pathname, -1,
+ (GElf_Addr) lib->base,
+ false) == NULL)
+ fprintf(stderr,
+ "dwfl_report_elf %s@%p (%s) %d: %s\n",
+ lib->soname, lib->base, lib->pathname,
+ proc->pid, dwfl_errmsg (-1));
+ dwfl_report_end(dwfl, NULL, NULL);
+
+ if (leader->dwfl == NULL) {
+ int r = dwfl_linux_proc_attach(dwfl,
+ leader->pid,
+ true);
+ if (r == 0)
+ leader->dwfl = dwfl;
+ else {
+ const char *msg;
+ dwfl_end(dwfl);
+ if (r < 0)
+ msg = dwfl_errmsg(-1);
+ else
+ msg = strerror(r);
+ fprintf(stderr, "Couldn't initialize "
+ "libdwfl unwinding for "
+ "process %d: %s\n",
+ leader->pid, msg);
+ }
+ }
+ }
+ }
+#endif /* defined(HAVE_LIBDW) */
+
/* Insert breakpoints for all active (non-latent) symbols. */
struct library_symbol *libsym = NULL;
while ((libsym = library_each_symbol(lib, libsym,
diff -u ltrace-0.7.91/proc.c.orig ltrace-0.7.91-pm/proc.c.orig
--- ltrace-0.7.91/proc.h 2015-01-09 00:38:17.966190936 +0100
+++ ltrace-0.7.91-pm/proc.h 2015-01-09 00:37:40.261910548 +0100
@@ -28,6 +28,10 @@
#include <sys/time.h>
#include <stdint.h>
+#if defined(HAVE_LIBDW)
+# include <elfutils/libdwfl.h>
+#endif
+
#if defined(HAVE_LIBUNWIND)
# include <libunwind.h>
#endif /* defined(HAVE_LIBUNWIND) */
@@ -113,6 +117,11 @@
short e_machine;
char e_class;
+#if defined(HAVE_LIBDW)
+ /* Unwind info for leader, NULL for non-leader procs. */
+ Dwfl *dwfl;
+#endif /* defined(HAVE_LIBDW) */
+
#if defined(HAVE_LIBUNWIND)
/* libunwind address space */
unw_addr_space_t unwind_as;
Only in ltrace-0.7.91-pm/: proc.h.orig
Common subdirectories: ltrace-0.7.91/sysdeps and ltrace-0.7.91-pm/sysdeps
Common subdirectories: ltrace-0.7.91/testsuite and ltrace-0.7.91-pm/testsuite
diff -up ltrace-0.7.91/proc.c\~ ltrace-0.7.91/proc.c
--- ltrace-0.7.91/proc.c~ 2015-01-09 01:55:38.289864078 +0100
+++ ltrace-0.7.91/proc.c 2015-01-09 01:56:29.818881935 +0100
@@ -918,7 +918,8 @@ proc_add_library(struct process *proc, s
dwfl_report_begin_add(dwfl);
if (dwfl_report_elf(dwfl, lib->soname,
lib->pathname, -1,
- (GElf_Addr) lib->base,
+ /* XXX double cast */
+ (GElf_Addr) (uintptr_t) lib->base,
false) == NULL)
fprintf(stderr,
"dwfl_report_elf %s@%p (%s) %d: %s\n",

View File

@ -0,0 +1,101 @@
From fba95ad936f1d8c1052259bae811f1fc07f9a215 Mon Sep 17 00:00:00 2001
From: Petr Machata <pmachata@redhat.com>
Date: Thu, 30 Oct 2014 01:48:17 +0100
Subject: [PATCH] Initialize the PLT slot map correctly on x86 and x86_64
The PLT slot map translates relocation numbers to PLT slot numbers,
but was actually initialized in the opposite direction. Fix the way
it's initialized. This bug can be seen on glibc in particular:
$ ltrace -e free ls
libc.so.6->free(0x5) = <void>
libc.so.6->free(0x78) = <void>
libc.so.6->free(0xc) = <void>
libc.so.6->free(0x308) = <void>
Note the nonsense values passed to free. The problem is that these
are not free calls at all, but malloc calls that are assigned to wrong
PLT slots due to above bug.
---
sysdeps/linux-gnu/x86/plt.c | 38 +++++++++++++++++++++-----------------
1 file changed, 21 insertions(+), 17 deletions(-)
diff --git a/sysdeps/linux-gnu/x86/plt.c b/sysdeps/linux-gnu/x86/plt.c
index c860af6..97f6c3e 100644
--- a/sysdeps/linux-gnu/x86/plt.c
+++ b/sysdeps/linux-gnu/x86/plt.c
@@ -77,6 +77,18 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
{
VECT_INIT(&lte->arch.plt_map, unsigned int);
+ if (vect_reserve(&lte->arch.plt_map, vect_size(&lte->plt_relocs)) < 0) {
+ fail:
+ arch_elf_destroy(lte);
+ return -1;
+ }
+
+ {
+ unsigned int i, sz = vect_size(&lte->plt_relocs);
+ for (i = 0; i < sz; ++i)
+ vect_pushback (&lte->arch.plt_map, &i);
+ }
+
/* IRELATIVE slots may make the whole situation a fair deal
* more complex. On x86{,_64}, the PLT slots are not
* presented in the order of the corresponding relocations,
@@ -114,43 +126,35 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
/* Here we scan the PLT table and initialize a map of
* relocation->slot number in lte->arch.plt_map. */
- size_t i;
- for (i = 0; i < vect_size(&lte->plt_relocs); ++i) {
+ unsigned int i, sz = vect_size(&lte->plt_relocs);
+ for (i = 0; i < sz; ++i) {
GElf_Addr offset = x86_plt_offset(i);
- uint32_t reloc_arg = 0;
uint8_t byte;
if (elf_read_next_u8(lte->plt_data, &offset, &byte) < 0
|| byte != 0xff
|| elf_read_next_u8(lte->plt_data, &offset, &byte) < 0
|| (byte != 0xa3 && byte != 0x25))
- goto next;
+ continue;
/* Skip immediate argument in the instruction. */
offset += 4;
+ uint32_t reloc_arg;
if (elf_read_next_u8(lte->plt_data, &offset, &byte) < 0
|| byte != 0x68
|| elf_read_next_u32(lte->plt_data,
- &offset, &reloc_arg) < 0) {
- reloc_arg = 0;
- goto next;
- }
+ &offset, &reloc_arg) < 0)
+ continue;
if (lte->ehdr.e_machine == EM_386) {
- if (reloc_arg % 8 != 0) {
- reloc_arg = 0;
- goto next;
- }
+ if (reloc_arg % 8 != 0)
+ continue;
reloc_arg /= 8;
}
- next:
- if (VECT_PUSHBACK(&lte->arch.plt_map, &reloc_arg) < 0) {
- arch_elf_destroy(lte);
- return -1;
- }
+ *VECT_ELEMENT(&lte->arch.plt_map, unsigned int, reloc_arg) = i;
}
return 0;
--
2.1.0

View File

@ -0,0 +1,32 @@
From e16a28f1b6e5a15368f8ed98dc29a6da714dc5fa Mon Sep 17 00:00:00 2001
From: Petr Machata <pmachata@redhat.com>
Date: Tue, 9 Dec 2014 17:44:30 +0100
Subject: [PATCH] Drop unused label in x86 backend
---
sysdeps/linux-gnu/x86/plt.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/sysdeps/linux-gnu/x86/plt.c b/sysdeps/linux-gnu/x86/plt.c
index 97f6c3e..44ea260 100644
--- a/sysdeps/linux-gnu/x86/plt.c
+++ b/sysdeps/linux-gnu/x86/plt.c
@@ -1,6 +1,6 @@
/*
* This file is part of ltrace.
- * Copyright (C) 2013 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2013,2014 Petr Machata, Red Hat Inc.
* Copyright (C) 2004,2008,2009 Juan Cespedes
*
* This program is free software; you can redistribute it and/or
@@ -78,7 +78,6 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
VECT_INIT(&lte->arch.plt_map, unsigned int);
if (vect_reserve(&lte->arch.plt_map, vect_size(&lte->plt_relocs)) < 0) {
- fail:
arch_elf_destroy(lte);
return -1;
}
--
2.1.0

View File

@ -0,0 +1,156 @@
@@ -, +, @@
relocation
- In general they are. But IRELATIVE relocations are sorted to come
last, and PLT entries are not sorted accordingly.
---
sysdeps/linux-gnu/x86/arch.h | 11 +++++
sysdeps/linux-gnu/x86/plt.c | 101 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 111 insertions(+), 1 deletions(-)
--- a/sysdeps/linux-gnu/x86/arch.h
+++ a/sysdeps/linux-gnu/x86/arch.h
@@ -19,6 +19,10 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
+#ifndef LTRACE_X86_ARCH_H
+#define LTRACE_X86_ARCH_H
+
+#include "vect.h"
#define BREAKPOINT_VALUE {0xcc}
#define BREAKPOINT_LENGTH 1
@@ -30,9 +34,16 @@
#define ARCH_HAVE_ADD_PLT_ENTRY
+#define ARCH_HAVE_LTELF_DATA
+struct arch_ltelf_data {
+ struct vect plt_map;
+};
+
#ifdef __x86_64__
#define LT_ELFCLASS ELFCLASS64
#define LT_ELF_MACHINE EM_X86_64
#endif
#define LT_ELFCLASS2 ELFCLASS32
#define LT_ELF_MACHINE2 EM_386
+
+#endif /* LTRACE_X86_ARCH_H */
--- a/sysdeps/linux-gnu/x86/plt.c
+++ a/sysdeps/linux-gnu/x86/plt.c
@@ -27,10 +27,19 @@
#include "library.h"
#include "trace.h"
+static GElf_Addr
+x86_plt_offset(uint32_t i)
+{
+ /* Skip the first PLT entry, which contains a stub to call the
+ * resolver. */
+ return (i + 1) * 16;
+}
+
GElf_Addr
arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela)
{
- return lte->plt_addr + (ndx + 1) * 16;
+ uint32_t i = *VECT_ELEMENT(&lte->arch.plt_map, uint32_t, ndx);
+ return x86_plt_offset(i) + lte->plt_addr;
}
void *
@@ -62,3 +71,93 @@ arch_elf_add_plt_entry(struct process *proc, struct ltelf *lte,
return PLT_DEFAULT;
}
+
+int
+arch_elf_init(struct ltelf *lte, struct library *lib)
+{
+ VECT_INIT(&lte->arch.plt_map, unsigned int);
+
+ /* IRELATIVE slots may make the whole situation a fair deal
+ * more complex. On x86{,_64}, the PLT slots are not
+ * presented in the order of the corresponding relocations,
+ * but in the order it which these symbols are in the symbol
+ * table. That's static symbol table, which may be stripped
+ * off, not dynsym--that doesn't contain IFUNC symbols at all.
+ * So we have to decode each PLT entry to figure out what
+ * entry it corresponds to. We need to interpret the PLT
+ * table to figure this out.
+ *
+ * On i386, the PLT entry format is as follows:
+ *
+ * 8048300: ff 25 0c a0 04 08 jmp *0x804a00c
+ * 8048306: 68 20 00 00 00 push $0x20
+ * 804830b: e9 e0 ff ff ff jmp 80482f0 <_init+0x30>
+ *
+ * For PIE binaries it is the following:
+ *
+ * 410: ff a3 10 00 00 00 jmp *0x10(%ebx)
+ * 416: 68 00 00 00 00 push $0x0
+ * 41b: e9 d0 ff ff ff jmp 3f0 <_init+0x30>
+ *
+ * On x86_64, it is:
+ *
+ * 400420: ff 25 f2 0b 20 00 jmpq *0x200bf2(%rip) # 601018 <_GLOBAL_OFFSET_TABLE_+0x18>
+ * 400426: 68 00 00 00 00 pushq $0x0
+ * 40042b: e9 e0 ff ff ff jmpq 400410 <_init+0x18>
+ *
+ * On i386, the argument to push is an offset of relocation to
+ * use. The first PLT slot has an offset of 0x0, the second
+ * 0x8, etc. On x86_64, it's directly the index that we are
+ * looking for.
+ */
+
+ /* Here we scan the PLT table and initialize a map of
+ * relocation->slot number in lte->arch.plt_map. */
+
+ size_t i;
+ for (i = 0; i < vect_size(&lte->plt_relocs); ++i) {
+
+ GElf_Addr offset = x86_plt_offset(i);
+ uint32_t reloc_arg = 0;
+
+ uint8_t byte;
+ if (elf_read_next_u8(lte->plt_data, &offset, &byte) < 0
+ || byte != 0xff
+ || elf_read_next_u8(lte->plt_data, &offset, &byte) < 0
+ || (byte != 0xa3 && byte != 0x25))
+ goto next;
+
+ /* Skip immediate argument in the instruction. */
+ offset += 4;
+
+ if (elf_read_next_u8(lte->plt_data, &offset, &byte) < 0
+ || byte != 0x68
+ || elf_read_next_u32(lte->plt_data,
+ &offset, &reloc_arg) < 0) {
+ reloc_arg = 0;
+ goto next;
+ }
+
+ if (lte->ehdr.e_machine == EM_386) {
+ if (reloc_arg % 8 != 0) {
+ reloc_arg = 0;
+ goto next;
+ }
+ reloc_arg /= 8;
+ }
+
+ next:
+ if (VECT_PUSHBACK(&lte->arch.plt_map, &reloc_arg) < 0) {
+ arch_elf_destroy(lte);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+void
+arch_elf_destroy(struct ltelf *lte)
+{
+ VECT_DESTROY(&lte->arch.plt_map, uint32_t, NULL, NULL);
+}
--

BIN
ltrace-0.7.91.tar.gz Normal file

Binary file not shown.

77
ltrace.spec Normal file
View File

@ -0,0 +1,77 @@
name: ltrace
Version: 0.7.91
Release: 29
Summary: Trace the Library and System Calls a Program Makes
License: GPLv2+
URL: https://gitlab.com/cespedes/ltrace
Source0: http://repository.timesys.com/buildsources/l/ltrace/ltrace-0.7.91/ltrace-0.7.91.tar.gz
Patch0001: ltrace-0.7.91-account_execl.patch
Patch0002: ltrace-0.7.91-x86_64-irelative.patch
Patch0003: ltrace-0.7.91-man.patch
Patch0004: ltrace-0.7.91-cant_open.patch
Patch0005: ltrace-0.7.91-aarch64.patch
Patch0006: ltrace-0.7.2-e_machine.patch
Patch0007: ltrace-0.7.91-parser-ws_after_id.patch
Patch0008: ltrace-0.7.91-x86-plt_map.patch
Patch0009: ltrace-0.7.91-x86-unused_label.patch
Patch0010: ltrace-0.7.91-unwind-elfutils.patch
Patch0011: ltrace-0.7.91-multithread-no-f-1.patch
Patch0012: ltrace-0.7.91-multithread-no-f-2.patch
Patch0013: ltrace-0.7.91-testsuite-includes.patch
Patch0014: ltrace-0.7.91-testsuite-includes-2.patch
Patch0015: ltrace-0.7.91-tautology.patch
Patch0016: ltrace-0.7.91-aarch64-params.patch
# patch for openEuler
Patch9000: bugfix-0001-ltrace-0.7.91-aarch64_be-compile-support.patch
Patch9001: bugfix-0001-ltrace-byteswap-instruction-in-arm-be8-mode.patch
Patch9002: bugfix-for-use-after-free-about-soname.patch
BuildRequires: elfutils-devel dejagnu libselinux-devel autoconf automake libtool
%description
Ltrace is a program that runs the specified command until it exits. It
intercepts and records the dynamic library calls that are called by the
executed process and the signals that are received by that process. It
can also intercept and print the system calls executed by the program.
The program to trace need not be recompiled for this, so you can use
ltrace on binaries for which you do not have access to the source.
This is still a work in progress, so, for example, the tracking to
child processes may fail or some things may not work as expected.
%package help
Summary: Help document for the ltrace package
%description help
Help document for the ltrace package.
%prep
%autosetup -n %{name}-%{version} -p1
%build
autoreconf -i
%configure --docdir=%{?_pkgdocdir}%{!?_pkgdocdir:%{_docdir}/%{name}-%{version}}
%make_build
%install
%make_install bindir=%{_bindir}
%check
timeout 180 make check ||:
%files
%doc NEWS CREDITS INSTALL README TODO COPYING
%{_bindir}/ltrace
%{_datadir}/ltrace
%files help
%{_mandir}/man1/ltrace.1*
%{_mandir}/man5/ltrace.conf.5*
%changelog
* Wed Nov 27 2019 daiqianwen <daiqianwen@huawei.com> - 0.7.91-29
- Package init.