import gcc-toolset-10-ltrace-0.7.91-1.el8
This commit is contained in:
		
						commit
						9d5a9b14f5
					
				
							
								
								
									
										1
									
								
								.gcc-toolset-10-ltrace.metadata
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gcc-toolset-10-ltrace.metadata
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | 74029042af10b0e9fca6acccb016ce096460a176 SOURCES/ltrace-0.7.91.tar.bz2 | ||||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | SOURCES/ltrace-0.7.91.tar.bz2 | ||||||
							
								
								
									
										20
									
								
								SOURCES/ltrace-0.7.2-e_machine.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								SOURCES/ltrace-0.7.2-e_machine.patch
									
									
									
									
									
										Normal 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 | ||||||
							
								
								
									
										37
									
								
								SOURCES/ltrace-0.7.91-aarch64-params.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								SOURCES/ltrace-0.7.91-aarch64-params.patch
									
									
									
									
									
										Normal 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
									
								
								SOURCES/ltrace-0.7.91-aarch64.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2416
									
								
								SOURCES/ltrace-0.7.91-aarch64.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										834
									
								
								SOURCES/ltrace-0.7.91-account_execl.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										834
									
								
								SOURCES/ltrace-0.7.91-account_execl.patch
									
									
									
									
									
										Normal 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 | ||||||
|  | 
 | ||||||
							
								
								
									
										610
									
								
								SOURCES/ltrace-0.7.91-arm.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										610
									
								
								SOURCES/ltrace-0.7.91-arm.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,610 @@ | |||||||
|  | diff --git a/ltrace-elf.c b/ltrace-elf.c
 | ||||||
|  | index 92b642b..6f86d56 100644
 | ||||||
|  | --- a/ltrace-elf.c
 | ||||||
|  | +++ b/ltrace-elf.c
 | ||||||
|  | @@ -531,6 +531,38 @@ elf_read_relocs(struct ltelf *lte, Elf_Scn *scn, GElf_Shdr *shdr,
 | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +int
 | ||||||
|  | +elf_load_dynamic_entry(struct ltelf *lte, int tag, GElf_Addr *valuep)
 | ||||||
|  | +{
 | ||||||
|  | +	Elf_Scn *scn;
 | ||||||
|  | +	GElf_Shdr shdr;
 | ||||||
|  | +	if (elf_get_section_type(lte, SHT_DYNAMIC, &scn, &shdr) < 0
 | ||||||
|  | +	    || scn == NULL) {
 | ||||||
|  | +	fail:
 | ||||||
|  | +		fprintf(stderr, "Couldn't get SHT_DYNAMIC: %s\n",
 | ||||||
|  | +			elf_errmsg(-1));
 | ||||||
|  | +		return -1;
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  | +	Elf_Data *data = elf_loaddata(scn, &shdr);
 | ||||||
|  | +	if (data == NULL)
 | ||||||
|  | +		goto fail;
 | ||||||
|  | +
 | ||||||
|  | +	size_t j;
 | ||||||
|  | +	for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
 | ||||||
|  | +		GElf_Dyn dyn;
 | ||||||
|  | +		if (gelf_getdyn(data, j, &dyn) == NULL)
 | ||||||
|  | +			goto fail;
 | ||||||
|  | +
 | ||||||
|  | +		if(dyn.d_tag == tag) {
 | ||||||
|  | +			*valuep = dyn.d_un.d_ptr;
 | ||||||
|  | +			return 0;
 | ||||||
|  | +		}
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  | +	return -1;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  static int | ||||||
|  |  ltelf_read_elf(struct ltelf *lte, const char *filename) | ||||||
|  |  { | ||||||
|  | diff --git a/ltrace-elf.h b/ltrace-elf.h
 | ||||||
|  | index ea14512..db4ffe9 100644
 | ||||||
|  | --- a/ltrace-elf.h
 | ||||||
|  | +++ b/ltrace-elf.h
 | ||||||
|  | @@ -139,6 +139,10 @@ struct elf_each_symbol_t {
 | ||||||
|  |  int elf_read_relocs(struct ltelf *lte, Elf_Scn *scn, GElf_Shdr *shdr, | ||||||
|  |  		    struct vect *rela_vec); | ||||||
|  |   | ||||||
|  | +/* Read a given DT_ TAG from LTE.  Value is returned in *VALUEP.
 | ||||||
|  | + * Returns 0 on success or a negative value on failure.  */
 | ||||||
|  | +int elf_load_dynamic_entry(struct ltelf *lte, int tag, GElf_Addr *valuep);
 | ||||||
|  | +
 | ||||||
|  |  /* Read, respectively, 1, 2, 4, or 8 bytes from Elf data at given | ||||||
|  |   * OFFSET, and store it in *RETP.  Returns 0 on success or a negative | ||||||
|  |   * value if there's not enough data.  */ | ||||||
|  | diff --git a/sysdeps/linux-gnu/arm/arch.h b/sysdeps/linux-gnu/arm/arch.h
 | ||||||
|  | index 58a7fdf..6d0d902 100644
 | ||||||
|  | --- a/sysdeps/linux-gnu/arm/arch.h
 | ||||||
|  | +++ b/sysdeps/linux-gnu/arm/arch.h
 | ||||||
|  | @@ -22,6 +22,8 @@
 | ||||||
|  |  #ifndef LTRACE_ARM_ARCH_H | ||||||
|  |  #define LTRACE_ARM_ARCH_H | ||||||
|  |   | ||||||
|  | +#include <libelf.h>
 | ||||||
|  | +
 | ||||||
|  |  #define ARCH_HAVE_ENABLE_BREAKPOINT 1 | ||||||
|  |  #define ARCH_HAVE_DISABLE_BREAKPOINT 1 | ||||||
|  |   | ||||||
|  | @@ -47,7 +49,7 @@ struct arch_breakpoint_data {
 | ||||||
|  |   | ||||||
|  |  #define ARCH_HAVE_LTELF_DATA | ||||||
|  |  struct arch_ltelf_data { | ||||||
|  | -	/* We have this only for the hooks.  */
 | ||||||
|  | +	Elf_Data *jmprel_data;
 | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  #define ARCH_HAVE_LIBRARY_DATA | ||||||
|  | diff --git a/sysdeps/linux-gnu/arm/fetch.c b/sysdeps/linux-gnu/arm/fetch.c
 | ||||||
|  | index 5081d78..b500448 100644
 | ||||||
|  | --- a/sysdeps/linux-gnu/arm/fetch.c
 | ||||||
|  | +++ b/sysdeps/linux-gnu/arm/fetch.c
 | ||||||
|  | @@ -32,200 +32,12 @@
 | ||||||
|  |  #include "backend.h" | ||||||
|  |  #include "fetch.h" | ||||||
|  |  #include "library.h" | ||||||
|  | -#include "ltrace-elf.h"
 | ||||||
|  |  #include "proc.h" | ||||||
|  |  #include "ptrace.h" | ||||||
|  |  #include "regs.h" | ||||||
|  |  #include "type.h" | ||||||
|  |  #include "value.h" | ||||||
|  |   | ||||||
|  | -static int
 | ||||||
|  | -get_hardfp(uint64_t abi_vfp_args)
 | ||||||
|  | -{
 | ||||||
|  | -	if (abi_vfp_args == 2)
 | ||||||
|  | -		fprintf(stderr,
 | ||||||
|  | -			"Tag_ABI_VFP_args value 2 (tool chain-specific "
 | ||||||
|  | -			"conventions) not supported.\n");
 | ||||||
|  | -	return abi_vfp_args == 1;
 | ||||||
|  | -}
 | ||||||
|  | -
 | ||||||
|  | -int
 | ||||||
|  | -arch_elf_init(struct ltelf *lte, struct library *lib)
 | ||||||
|  | -{
 | ||||||
|  | -	/* Nothing in this section is strictly critical.  It's not
 | ||||||
|  | -	 * that much of a deal if we fail to guess right whether the
 | ||||||
|  | -	 * ABI is softfp or hardfp.  */
 | ||||||
|  | -	unsigned hardfp = 0;
 | ||||||
|  | -
 | ||||||
|  | -	Elf_Scn *scn;
 | ||||||
|  | -	Elf_Data *data;
 | ||||||
|  | -	GElf_Shdr shdr;
 | ||||||
|  | -	if (elf_get_section_type(lte, SHT_ARM_ATTRIBUTES, &scn, &shdr) < 0
 | ||||||
|  | -	    || (scn != NULL && (data = elf_loaddata(scn, &shdr)) == NULL)) {
 | ||||||
|  | -		fprintf(stderr,
 | ||||||
|  | -			"Error when obtaining ARM attribute section: %s\n",
 | ||||||
|  | -			elf_errmsg(-1));
 | ||||||
|  | -		goto done;
 | ||||||
|  | -
 | ||||||
|  | -	} else if (scn != NULL && data != NULL) {
 | ||||||
|  | -		GElf_Xword offset = 0;
 | ||||||
|  | -		uint8_t version;
 | ||||||
|  | -		if (elf_read_next_u8(data, &offset, &version) < 0) {
 | ||||||
|  | -			goto done;
 | ||||||
|  | -		} else if (version != 'A') {
 | ||||||
|  | -			fprintf(stderr, "Unsupported ARM attribute section "
 | ||||||
|  | -				"version %d ('%c').\n", version, version);
 | ||||||
|  | -			goto done;
 | ||||||
|  | -		}
 | ||||||
|  | -
 | ||||||
|  | -		do {
 | ||||||
|  | -			const char signature[] = "aeabi";
 | ||||||
|  | -			/* N.B. LEN is including the length field
 | ||||||
|  | -			 * itself.  */
 | ||||||
|  | -			uint32_t sec_len;
 | ||||||
|  | -			if (elf_read_u32(data, offset, &sec_len) < 0
 | ||||||
|  | -			    || !elf_can_read_next(data, offset, sec_len)) {
 | ||||||
|  | -				goto done;
 | ||||||
|  | -			}
 | ||||||
|  | -			const GElf_Xword next_offset = offset + sec_len;
 | ||||||
|  | -			offset += 4;
 | ||||||
|  | -
 | ||||||
|  | -			if (sec_len < 4 + sizeof signature
 | ||||||
|  | -			    || strcmp(signature, data->d_buf + offset) != 0)
 | ||||||
|  | -				goto skip;
 | ||||||
|  | -			offset += sizeof signature;
 | ||||||
|  | -
 | ||||||
|  | -			const GElf_Xword offset0 = offset;
 | ||||||
|  | -			uint64_t tag;
 | ||||||
|  | -			uint32_t sub_len;
 | ||||||
|  | -			if (elf_read_next_uleb128(data, &offset, &tag) < 0
 | ||||||
|  | -			    || elf_read_next_u32(data, &offset, &sub_len) < 0
 | ||||||
|  | -			    || !elf_can_read_next(data, offset0, sub_len))
 | ||||||
|  | -				goto done;
 | ||||||
|  | -
 | ||||||
|  | -			if (tag != 1)
 | ||||||
|  | -				/* IHI0045D_ABI_addenda: "section and
 | ||||||
|  | -				 * symbol attributes are deprecated
 | ||||||
|  | -				 * [...] consumers are permitted to
 | ||||||
|  | -				 * ignore them."  */
 | ||||||
|  | -				goto skip;
 | ||||||
|  | -
 | ||||||
|  | -			while (offset < offset0 + sub_len) {
 | ||||||
|  | -				if (elf_read_next_uleb128(data,
 | ||||||
|  | -							  &offset, &tag) < 0)
 | ||||||
|  | -					goto done;
 | ||||||
|  | -
 | ||||||
|  | -				switch (tag) {
 | ||||||
|  | -					uint64_t v;
 | ||||||
|  | -				case 6: /* Tag_CPU_arch */
 | ||||||
|  | -				case 7: /* Tag_CPU_arch_profile */
 | ||||||
|  | -				case 8: /* Tag_ARM_ISA_use */
 | ||||||
|  | -				case 9: /* Tag_THUMB_ISA_use */
 | ||||||
|  | -				case 10: /* Tag_FP_arch */
 | ||||||
|  | -				case 11: /* Tag_WMMX_arch */
 | ||||||
|  | -				case 12: /* Tag_Advanced_SIMD_arch */
 | ||||||
|  | -				case 13: /* Tag_PCS_config */
 | ||||||
|  | -				case 14: /* Tag_ABI_PCS_R9_use */
 | ||||||
|  | -				case 15: /* Tag_ABI_PCS_RW_data */
 | ||||||
|  | -				case 16: /* Tag_ABI_PCS_RO_data */
 | ||||||
|  | -				case 17: /* Tag_ABI_PCS_GOT_use */
 | ||||||
|  | -				case 18: /* Tag_ABI_PCS_wchar_t */
 | ||||||
|  | -				case 19: /* Tag_ABI_FP_rounding */
 | ||||||
|  | -				case 20: /* Tag_ABI_FP_denormal */
 | ||||||
|  | -				case 21: /* Tag_ABI_FP_exceptions */
 | ||||||
|  | -				case 22: /* Tag_ABI_FP_user_exceptions */
 | ||||||
|  | -				case 23: /* Tag_ABI_FP_number_model */
 | ||||||
|  | -				case 24: /* Tag_ABI_align_needed */
 | ||||||
|  | -				case 25: /* Tag_ABI_align_preserved */
 | ||||||
|  | -				case 26: /* Tag_ABI_enum_size */
 | ||||||
|  | -				case 27: /* Tag_ABI_HardFP_use */
 | ||||||
|  | -				case 28: /* Tag_ABI_VFP_args */
 | ||||||
|  | -				case 29: /* Tag_ABI_WMMX_args */
 | ||||||
|  | -				case 30: /* Tag_ABI_optimization_goals */
 | ||||||
|  | -				case 31: /* Tag_ABI_FP_optimization_goals */
 | ||||||
|  | -				case 32: /* Tag_compatibility */
 | ||||||
|  | -				case 34: /* Tag_CPU_unaligned_access */
 | ||||||
|  | -				case 36: /* Tag_FP_HP_extension */
 | ||||||
|  | -				case 38: /* Tag_ABI_FP_16bit_format */
 | ||||||
|  | -				case 42: /* Tag_MPextension_use */
 | ||||||
|  | -				case 70: /* Tag_MPextension_use as well */
 | ||||||
|  | -				case 44: /* Tag_DIV_use */
 | ||||||
|  | -				case 64: /* Tag_nodefaults */
 | ||||||
|  | -				case 66: /* Tag_T2EE_use */
 | ||||||
|  | -				case 68: /* Tag_Virtualization_use */
 | ||||||
|  | -				uleb128:
 | ||||||
|  | -					if (elf_read_next_uleb128
 | ||||||
|  | -						(data, &offset, &v) < 0)
 | ||||||
|  | -						goto done;
 | ||||||
|  | -					if (tag == 28)
 | ||||||
|  | -						hardfp = get_hardfp(v);
 | ||||||
|  | -					if (tag != 32)
 | ||||||
|  | -						continue;
 | ||||||
|  | -
 | ||||||
|  | -					/* Tag 32 has two arguments,
 | ||||||
|  | -					 * fall through.  */
 | ||||||
|  | -
 | ||||||
|  | -				case 4:	/* Tag_CPU_raw_name */
 | ||||||
|  | -				case 5:	/* Tag_CPU_name */
 | ||||||
|  | -				case 65: /* Tag_also_compatible_with */
 | ||||||
|  | -				case 67: /* Tag_conformance */
 | ||||||
|  | -				ntbs:
 | ||||||
|  | -					offset += strlen(data->d_buf
 | ||||||
|  | -							 + offset) + 1;
 | ||||||
|  | -					continue;
 | ||||||
|  | -				}
 | ||||||
|  | -
 | ||||||
|  | -				/* Handle unknown tags in a generic
 | ||||||
|  | -				 * manner, if possible.  */
 | ||||||
|  | -				if (tag <= 32) {
 | ||||||
|  | -					fprintf(stderr,
 | ||||||
|  | -						"Unknown tag %lld "
 | ||||||
|  | -						"at offset %#llx "
 | ||||||
|  | -						"of ARM attribute section.",
 | ||||||
|  | -						tag, offset);
 | ||||||
|  | -					goto skip;
 | ||||||
|  | -				} else if (tag % 2 == 0) {
 | ||||||
|  | -					goto uleb128;
 | ||||||
|  | -				} else {
 | ||||||
|  | -					goto ntbs;
 | ||||||
|  | -				}
 | ||||||
|  | -			}
 | ||||||
|  | -
 | ||||||
|  | -		skip:
 | ||||||
|  | -			offset = next_offset;
 | ||||||
|  | -
 | ||||||
|  | -		} while (elf_can_read_next(data, offset, 1));
 | ||||||
|  | -
 | ||||||
|  | -	}
 | ||||||
|  | -
 | ||||||
|  | -done:
 | ||||||
|  | -	lib->arch.hardfp = hardfp;
 | ||||||
|  | -	return 0;
 | ||||||
|  | -}
 | ||||||
|  | -
 | ||||||
|  | -void
 | ||||||
|  | -arch_elf_destroy(struct ltelf *lte)
 | ||||||
|  | -{
 | ||||||
|  | -}
 | ||||||
|  | -
 | ||||||
|  | -int
 | ||||||
|  | -arch_library_init(struct library *lib)
 | ||||||
|  | -{
 | ||||||
|  | -	return 0;
 | ||||||
|  | -}
 | ||||||
|  | -
 | ||||||
|  | -void
 | ||||||
|  | -arch_library_destroy(struct library *lib)
 | ||||||
|  | -{
 | ||||||
|  | -}
 | ||||||
|  | -
 | ||||||
|  | -int
 | ||||||
|  | -arch_library_clone(struct library *retp, struct library *lib)
 | ||||||
|  | -{
 | ||||||
|  | -	retp->arch = lib->arch;
 | ||||||
|  | -	return 0;
 | ||||||
|  | -}
 | ||||||
|  | -
 | ||||||
|  |  enum { | ||||||
|  |  	/* How many (double) VFP registers the AAPCS uses for | ||||||
|  |  	 * parameter passing.  */ | ||||||
|  | diff --git a/sysdeps/linux-gnu/arm/plt.c b/sysdeps/linux-gnu/arm/plt.c
 | ||||||
|  | index d1bf7ca..9e9e37f 100644
 | ||||||
|  | --- a/sysdeps/linux-gnu/arm/plt.c
 | ||||||
|  | +++ b/sysdeps/linux-gnu/arm/plt.c
 | ||||||
|  | @@ -1,5 +1,6 @@
 | ||||||
|  |  /* | ||||||
|  |   * This file is part of ltrace. | ||||||
|  | + * Copyright (C) 2013 Petr Machata, Red Hat Inc.
 | ||||||
|  |   * Copyright (C) 2010 Zach Welch, CodeSourcery | ||||||
|  |   * Copyright (C) 2004,2008,2009 Juan Cespedes | ||||||
|  |   * | ||||||
|  | @@ -20,20 +21,205 @@
 | ||||||
|  |   */ | ||||||
|  |   | ||||||
|  |  #include <gelf.h> | ||||||
|  | +#include <stdio.h>
 | ||||||
|  | +#include <string.h>
 | ||||||
|  |   | ||||||
|  |  #include "proc.h" | ||||||
|  |  #include "library.h" | ||||||
|  |  #include "ltrace-elf.h" | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | +get_hardfp(uint64_t abi_vfp_args)
 | ||||||
|  | +{
 | ||||||
|  | +	if (abi_vfp_args == 2)
 | ||||||
|  | +		fprintf(stderr,
 | ||||||
|  | +			"Tag_ABI_VFP_args value 2 (tool chain-specific "
 | ||||||
|  | +			"conventions) not supported.\n");
 | ||||||
|  | +	return abi_vfp_args == 1;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +int
 | ||||||
|  | +arch_elf_init(struct ltelf *lte, struct library *lib)
 | ||||||
|  | +{
 | ||||||
|  | +	GElf_Addr jmprel_addr;
 | ||||||
|  | +	Elf_Scn *jmprel_sec;
 | ||||||
|  | +	GElf_Shdr jmprel_shdr;
 | ||||||
|  | +	if (elf_load_dynamic_entry(lte, DT_JMPREL, &jmprel_addr) < 0
 | ||||||
|  | +	    || elf_get_section_covering(lte, jmprel_addr,
 | ||||||
|  | +					&jmprel_sec, &jmprel_shdr) < 0
 | ||||||
|  | +	    || jmprel_sec == NULL)
 | ||||||
|  | +		return -1;
 | ||||||
|  | +
 | ||||||
|  | +	lte->arch.jmprel_data = elf_loaddata(jmprel_sec, &jmprel_shdr);
 | ||||||
|  | +	if (lte->arch.jmprel_data == NULL)
 | ||||||
|  | +		return -1;
 | ||||||
|  | +
 | ||||||
|  | +	/* Nothing in this section is strictly critical.  It's not
 | ||||||
|  | +	 * that much of a deal if we fail to guess right whether the
 | ||||||
|  | +	 * ABI is softfp or hardfp.  */
 | ||||||
|  | +	unsigned hardfp = 0;
 | ||||||
|  | +
 | ||||||
|  | +	Elf_Scn *scn;
 | ||||||
|  | +	Elf_Data *data;
 | ||||||
|  | +	GElf_Shdr shdr;
 | ||||||
|  | +	if (elf_get_section_type(lte, SHT_ARM_ATTRIBUTES, &scn, &shdr) < 0
 | ||||||
|  | +	    || (scn != NULL && (data = elf_loaddata(scn, &shdr)) == NULL)) {
 | ||||||
|  | +		fprintf(stderr,
 | ||||||
|  | +			"Error when obtaining ARM attribute section: %s\n",
 | ||||||
|  | +			elf_errmsg(-1));
 | ||||||
|  | +		goto done;
 | ||||||
|  | +
 | ||||||
|  | +	} else if (scn != NULL && data != NULL) {
 | ||||||
|  | +		GElf_Xword offset = 0;
 | ||||||
|  | +		uint8_t version;
 | ||||||
|  | +		if (elf_read_next_u8(data, &offset, &version) < 0) {
 | ||||||
|  | +			goto done;
 | ||||||
|  | +		} else if (version != 'A') {
 | ||||||
|  | +			fprintf(stderr, "Unsupported ARM attribute section "
 | ||||||
|  | +				"version %d ('%c').\n", version, version);
 | ||||||
|  | +			goto done;
 | ||||||
|  | +		}
 | ||||||
|  | +
 | ||||||
|  | +		do {
 | ||||||
|  | +			const char signature[] = "aeabi";
 | ||||||
|  | +			/* N.B. LEN is including the length field
 | ||||||
|  | +			 * itself.  */
 | ||||||
|  | +			uint32_t sec_len;
 | ||||||
|  | +			if (elf_read_u32(data, offset, &sec_len) < 0
 | ||||||
|  | +			    || !elf_can_read_next(data, offset, sec_len)) {
 | ||||||
|  | +				goto done;
 | ||||||
|  | +			}
 | ||||||
|  | +			const GElf_Xword next_offset = offset + sec_len;
 | ||||||
|  | +			offset += 4;
 | ||||||
|  | +
 | ||||||
|  | +			if (sec_len < 4 + sizeof signature
 | ||||||
|  | +			    || strcmp(signature, data->d_buf + offset) != 0)
 | ||||||
|  | +				goto skip;
 | ||||||
|  | +			offset += sizeof signature;
 | ||||||
|  | +
 | ||||||
|  | +			const GElf_Xword offset0 = offset;
 | ||||||
|  | +			uint64_t tag;
 | ||||||
|  | +			uint32_t sub_len;
 | ||||||
|  | +			if (elf_read_next_uleb128(data, &offset, &tag) < 0
 | ||||||
|  | +			    || elf_read_next_u32(data, &offset, &sub_len) < 0
 | ||||||
|  | +			    || !elf_can_read_next(data, offset0, sub_len))
 | ||||||
|  | +				goto done;
 | ||||||
|  | +
 | ||||||
|  | +			if (tag != 1)
 | ||||||
|  | +				/* IHI0045D_ABI_addenda: "section and
 | ||||||
|  | +				 * symbol attributes are deprecated
 | ||||||
|  | +				 * [...] consumers are permitted to
 | ||||||
|  | +				 * ignore them."  */
 | ||||||
|  | +				goto skip;
 | ||||||
|  | +
 | ||||||
|  | +			while (offset < offset0 + sub_len) {
 | ||||||
|  | +				if (elf_read_next_uleb128(data,
 | ||||||
|  | +							  &offset, &tag) < 0)
 | ||||||
|  | +					goto done;
 | ||||||
|  | +
 | ||||||
|  | +				switch (tag) {
 | ||||||
|  | +					uint64_t v;
 | ||||||
|  | +				case 6: /* Tag_CPU_arch */
 | ||||||
|  | +				case 7: /* Tag_CPU_arch_profile */
 | ||||||
|  | +				case 8: /* Tag_ARM_ISA_use */
 | ||||||
|  | +				case 9: /* Tag_THUMB_ISA_use */
 | ||||||
|  | +				case 10: /* Tag_FP_arch */
 | ||||||
|  | +				case 11: /* Tag_WMMX_arch */
 | ||||||
|  | +				case 12: /* Tag_Advanced_SIMD_arch */
 | ||||||
|  | +				case 13: /* Tag_PCS_config */
 | ||||||
|  | +				case 14: /* Tag_ABI_PCS_R9_use */
 | ||||||
|  | +				case 15: /* Tag_ABI_PCS_RW_data */
 | ||||||
|  | +				case 16: /* Tag_ABI_PCS_RO_data */
 | ||||||
|  | +				case 17: /* Tag_ABI_PCS_GOT_use */
 | ||||||
|  | +				case 18: /* Tag_ABI_PCS_wchar_t */
 | ||||||
|  | +				case 19: /* Tag_ABI_FP_rounding */
 | ||||||
|  | +				case 20: /* Tag_ABI_FP_denormal */
 | ||||||
|  | +				case 21: /* Tag_ABI_FP_exceptions */
 | ||||||
|  | +				case 22: /* Tag_ABI_FP_user_exceptions */
 | ||||||
|  | +				case 23: /* Tag_ABI_FP_number_model */
 | ||||||
|  | +				case 24: /* Tag_ABI_align_needed */
 | ||||||
|  | +				case 25: /* Tag_ABI_align_preserved */
 | ||||||
|  | +				case 26: /* Tag_ABI_enum_size */
 | ||||||
|  | +				case 27: /* Tag_ABI_HardFP_use */
 | ||||||
|  | +				case 28: /* Tag_ABI_VFP_args */
 | ||||||
|  | +				case 29: /* Tag_ABI_WMMX_args */
 | ||||||
|  | +				case 30: /* Tag_ABI_optimization_goals */
 | ||||||
|  | +				case 31: /* Tag_ABI_FP_optimization_goals */
 | ||||||
|  | +				case 32: /* Tag_compatibility */
 | ||||||
|  | +				case 34: /* Tag_CPU_unaligned_access */
 | ||||||
|  | +				case 36: /* Tag_FP_HP_extension */
 | ||||||
|  | +				case 38: /* Tag_ABI_FP_16bit_format */
 | ||||||
|  | +				case 42: /* Tag_MPextension_use */
 | ||||||
|  | +				case 70: /* Tag_MPextension_use as well */
 | ||||||
|  | +				case 44: /* Tag_DIV_use */
 | ||||||
|  | +				case 64: /* Tag_nodefaults */
 | ||||||
|  | +				case 66: /* Tag_T2EE_use */
 | ||||||
|  | +				case 68: /* Tag_Virtualization_use */
 | ||||||
|  | +				uleb128:
 | ||||||
|  | +					if (elf_read_next_uleb128
 | ||||||
|  | +						(data, &offset, &v) < 0)
 | ||||||
|  | +						goto done;
 | ||||||
|  | +					if (tag == 28)
 | ||||||
|  | +						hardfp = get_hardfp(v);
 | ||||||
|  | +					if (tag != 32)
 | ||||||
|  | +						continue;
 | ||||||
|  | +
 | ||||||
|  | +					/* Tag 32 has two arguments,
 | ||||||
|  | +					 * fall through.  */
 | ||||||
|  | +
 | ||||||
|  | +				case 4:	/* Tag_CPU_raw_name */
 | ||||||
|  | +				case 5:	/* Tag_CPU_name */
 | ||||||
|  | +				case 65: /* Tag_also_compatible_with */
 | ||||||
|  | +				case 67: /* Tag_conformance */
 | ||||||
|  | +				ntbs:
 | ||||||
|  | +					offset += strlen(data->d_buf
 | ||||||
|  | +							 + offset) + 1;
 | ||||||
|  | +					continue;
 | ||||||
|  | +				}
 | ||||||
|  | +
 | ||||||
|  | +				/* Handle unknown tags in a generic
 | ||||||
|  | +				 * manner, if possible.  */
 | ||||||
|  | +				if (tag <= 32) {
 | ||||||
|  | +					fprintf(stderr,
 | ||||||
|  | +						"Unknown tag %lld "
 | ||||||
|  | +						"at offset %#llx "
 | ||||||
|  | +						"of ARM attribute section.",
 | ||||||
|  | +						tag, offset);
 | ||||||
|  | +					goto skip;
 | ||||||
|  | +				} else if (tag % 2 == 0) {
 | ||||||
|  | +					goto uleb128;
 | ||||||
|  | +				} else {
 | ||||||
|  | +					goto ntbs;
 | ||||||
|  | +				}
 | ||||||
|  | +			}
 | ||||||
|  | +
 | ||||||
|  | +		skip:
 | ||||||
|  | +			offset = next_offset;
 | ||||||
|  | +
 | ||||||
|  | +		} while (elf_can_read_next(data, offset, 1));
 | ||||||
|  | +
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  | +done:
 | ||||||
|  | +	lib->arch.hardfp = hardfp;
 | ||||||
|  | +	return 0;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +void
 | ||||||
|  | +arch_elf_destroy(struct ltelf *lte)
 | ||||||
|  | +{
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +static int
 | ||||||
|  |  arch_plt_entry_has_stub(struct ltelf *lte, size_t off) { | ||||||
|  | -	uint16_t op = *(uint16_t *)((char *)lte->relplt->d_buf + off);
 | ||||||
|  | +	char *buf = (char *) lte->arch.jmprel_data->d_buf;
 | ||||||
|  | +	uint16_t op = *(uint16_t *) (buf + off);
 | ||||||
|  |  	return op == 0x4778; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  GElf_Addr | ||||||
|  |  arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) { | ||||||
|  | -	size_t start = lte->relplt->d_size + 12;
 | ||||||
|  | +	size_t start = lte->arch.jmprel_data->d_size + 12;
 | ||||||
|  |  	size_t off = start + 20, i; | ||||||
|  |  	for (i = 0; i < ndx; i++) | ||||||
|  |  		off += arch_plt_entry_has_stub(lte, off) ? 16 : 12; | ||||||
|  | @@ -47,3 +233,21 @@ sym2addr(struct process *proc, struct library_symbol *sym)
 | ||||||
|  |  { | ||||||
|  |  	return sym->enter_addr; | ||||||
|  |  } | ||||||
|  | +
 | ||||||
|  | +int
 | ||||||
|  | +arch_library_init(struct library *lib)
 | ||||||
|  | +{
 | ||||||
|  | +	return 0;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +void
 | ||||||
|  | +arch_library_destroy(struct library *lib)
 | ||||||
|  | +{
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +int
 | ||||||
|  | +arch_library_clone(struct library *retp, struct library *lib)
 | ||||||
|  | +{
 | ||||||
|  | +	retp->arch = lib->arch;
 | ||||||
|  | +	return 0;
 | ||||||
|  | +}
 | ||||||
|  | diff --git a/sysdeps/linux-gnu/ppc/plt.c b/sysdeps/linux-gnu/ppc/plt.c
 | ||||||
|  | index 5e3ffe1..3ec1397 100644
 | ||||||
|  | --- a/sysdeps/linux-gnu/ppc/plt.c
 | ||||||
|  | +++ b/sysdeps/linux-gnu/ppc/plt.c
 | ||||||
|  | @@ -402,38 +402,6 @@ get_glink_vma(struct ltelf *lte, GElf_Addr ppcgot, Elf_Data *plt_data)
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | -load_dynamic_entry(struct ltelf *lte, int tag, GElf_Addr *valuep)
 | ||||||
|  | -{
 | ||||||
|  | -	Elf_Scn *scn;
 | ||||||
|  | -	GElf_Shdr shdr;
 | ||||||
|  | -	if (elf_get_section_type(lte, SHT_DYNAMIC, &scn, &shdr) < 0
 | ||||||
|  | -	    || scn == NULL) {
 | ||||||
|  | -	fail:
 | ||||||
|  | -		fprintf(stderr, "Couldn't get SHT_DYNAMIC: %s\n",
 | ||||||
|  | -			elf_errmsg(-1));
 | ||||||
|  | -		return -1;
 | ||||||
|  | -	}
 | ||||||
|  | -
 | ||||||
|  | -	Elf_Data *data = elf_loaddata(scn, &shdr);
 | ||||||
|  | -	if (data == NULL)
 | ||||||
|  | -		goto fail;
 | ||||||
|  | -
 | ||||||
|  | -	size_t j;
 | ||||||
|  | -	for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
 | ||||||
|  | -		GElf_Dyn dyn;
 | ||||||
|  | -		if (gelf_getdyn(data, j, &dyn) == NULL)
 | ||||||
|  | -			goto fail;
 | ||||||
|  | -
 | ||||||
|  | -		if(dyn.d_tag == tag) {
 | ||||||
|  | -			*valuep = dyn.d_un.d_ptr;
 | ||||||
|  | -			return 0;
 | ||||||
|  | -		}
 | ||||||
|  | -	}
 | ||||||
|  | -
 | ||||||
|  | -	return -1;
 | ||||||
|  | -}
 | ||||||
|  | -
 | ||||||
|  | -static int
 | ||||||
|  |  nonzero_data(Elf_Data *data) | ||||||
|  |  { | ||||||
|  |  	/* We are not supposed to get here if there's no PLT.  */ | ||||||
|  | @@ -488,8 +456,8 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
 | ||||||
|  |  	Elf_Scn *rela_sec; | ||||||
|  |  	GElf_Shdr rela_shdr; | ||||||
|  |  	if ((lte->ehdr.e_machine == EM_PPC64 || lte->arch.secure_plt) | ||||||
|  | -	    && load_dynamic_entry(lte, DT_RELA, &rela) == 0
 | ||||||
|  | -	    && load_dynamic_entry(lte, DT_RELASZ, &relasz) == 0
 | ||||||
|  | +	    && elf_load_dynamic_entry(lte, DT_RELA, &rela) == 0
 | ||||||
|  | +	    && elf_load_dynamic_entry(lte, DT_RELASZ, &relasz) == 0
 | ||||||
|  |  	    && elf_get_section_covering(lte, rela, &rela_sec, &rela_shdr) == 0 | ||||||
|  |  	    && rela_sec != NULL) { | ||||||
|  |   | ||||||
|  | @@ -509,7 +477,7 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
 | ||||||
|  |   | ||||||
|  |  	if (lte->ehdr.e_machine == EM_PPC && lte->arch.secure_plt) { | ||||||
|  |  		GElf_Addr ppcgot; | ||||||
|  | -		if (load_dynamic_entry(lte, DT_PPC_GOT, &ppcgot) < 0) {
 | ||||||
|  | +		if (elf_load_dynamic_entry(lte, DT_PPC_GOT, &ppcgot) < 0) {
 | ||||||
|  |  			fprintf(stderr, "couldn't find DT_PPC_GOT\n"); | ||||||
|  |  			return -1; | ||||||
|  |  		} | ||||||
|  | @@ -522,7 +490,8 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
 | ||||||
|  |   | ||||||
|  |  	} else if (lte->ehdr.e_machine == EM_PPC64) { | ||||||
|  |  		GElf_Addr glink_vma; | ||||||
|  | -		if (load_dynamic_entry(lte, DT_PPC64_GLINK, &glink_vma) < 0) {
 | ||||||
|  | +		if (elf_load_dynamic_entry(lte, DT_PPC64_GLINK,
 | ||||||
|  | +					   &glink_vma) < 0) {
 | ||||||
|  |  			fprintf(stderr, "couldn't find DT_PPC64_GLINK\n"); | ||||||
|  |  			return -1; | ||||||
|  |  		} | ||||||
|  | @@ -532,8 +501,8 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
 | ||||||
|  |   | ||||||
|  |  	} else { | ||||||
|  |  		/* By exhaustion--PPC32 BSS.  */ | ||||||
|  | -		if (load_dynamic_entry(lte, DT_PLTGOT,
 | ||||||
|  | -				       &lib->arch.pltgot_addr) < 0) {
 | ||||||
|  | +		if (elf_load_dynamic_entry(lte, DT_PLTGOT,
 | ||||||
|  | +					   &lib->arch.pltgot_addr) < 0) {
 | ||||||
|  |  			fprintf(stderr, "couldn't find DT_PLTGOT\n"); | ||||||
|  |  			return -1; | ||||||
|  |  		} | ||||||
							
								
								
									
										81
									
								
								SOURCES/ltrace-0.7.91-breakpoint-on_install.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								SOURCES/ltrace-0.7.91-breakpoint-on_install.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,81 @@ | |||||||
|  | From 56134ff5442bee4e128b189bb86cfc97dcb6f60a Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Petr Machata <pmachata@redhat.com> | ||||||
|  | Date: Fri, 10 Jan 2014 20:05:15 +0100 | ||||||
|  | Subject: [PATCH 1/2] Add a new per-breakpoint callback on_install | ||||||
|  | 
 | ||||||
|  | ---
 | ||||||
|  |  breakpoint.h  |    9 ++++++++- | ||||||
|  |  breakpoints.c |   11 ++++++++++- | ||||||
|  |  2 files changed, 18 insertions(+), 2 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/breakpoint.h b/breakpoint.h
 | ||||||
|  | index 95964a8..c36f673 100644
 | ||||||
|  | --- a/breakpoint.h
 | ||||||
|  | +++ b/breakpoint.h
 | ||||||
|  | @@ -1,6 +1,6 @@
 | ||||||
|  |  /* | ||||||
|  |   * 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.
 | ||||||
|  |   * Copyright (C) 2009 Juan Cespedes | ||||||
|  |   * | ||||||
|  |   * This program is free software; you can redistribute it and/or | ||||||
|  | @@ -46,6 +46,7 @@
 | ||||||
|  |  struct bp_callbacks { | ||||||
|  |  	void (*on_hit)(struct breakpoint *bp, struct process *proc); | ||||||
|  |  	void (*on_continue)(struct breakpoint *bp, struct process *proc); | ||||||
|  | +	void (*on_install)(struct breakpoint *bp, struct process *proc);
 | ||||||
|  |  	void (*on_retract)(struct breakpoint *bp, struct process *proc); | ||||||
|  |   | ||||||
|  |  	/* Create a new breakpoint that should handle return from the | ||||||
|  | @@ -84,6 +85,12 @@ void breakpoint_on_continue(struct breakpoint *bp, struct process *proc);
 | ||||||
|  |   * the instruction underneath it).  */ | ||||||
|  |  void breakpoint_on_retract(struct breakpoint *bp, struct process *proc); | ||||||
|  |   | ||||||
|  | +/* Call ON_INSTALL handler of BP, if any is set.  This should be
 | ||||||
|  | + * called after the breakpoint is enabled for the first time, not
 | ||||||
|  | + * every time it's enabled (such as after stepping over a site of a
 | ||||||
|  | + * temporarily disabled breakpoint).  */
 | ||||||
|  | +void breakpoint_on_install(struct breakpoint *bp, struct process *proc);
 | ||||||
|  | +
 | ||||||
|  |  /* Call GET_RETURN_BP handler of BP, if any is set.  If none is set, | ||||||
|  |   * call CREATE_DEFAULT_RETURN_BP to obtain one.  */ | ||||||
|  |  int breakpoint_get_return_bp(struct breakpoint **ret, | ||||||
|  | diff --git a/breakpoints.c b/breakpoints.c
 | ||||||
|  | index 947cb71..c3fa275 100644
 | ||||||
|  | --- a/breakpoints.c
 | ||||||
|  | +++ b/breakpoints.c
 | ||||||
|  | @@ -1,6 +1,6 @@
 | ||||||
|  |  /* | ||||||
|  |   * This file is part of ltrace. | ||||||
|  | - * Copyright (C) 2006,2007,2011,2012,2013 Petr Machata, Red Hat Inc.
 | ||||||
|  | + * Copyright (C) 2006,2007,2011,2012,2013,2014 Petr Machata, Red Hat Inc.
 | ||||||
|  |   * Copyright (C) 2009 Juan Cespedes | ||||||
|  |   * Copyright (C) 1998,2001,2002,2003,2007,2008,2009 Juan Cespedes | ||||||
|  |   * Copyright (C) 2006 Ian Wienand | ||||||
|  | @@ -85,6 +85,14 @@ breakpoint_on_retract(struct breakpoint *bp, struct process *proc)
 | ||||||
|  |  		(bp->cbs->on_retract)(bp, proc); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +void
 | ||||||
|  | +breakpoint_on_install(struct breakpoint *bp, struct process *proc)
 | ||||||
|  | +{
 | ||||||
|  | +	assert(bp != NULL);
 | ||||||
|  | +	if (bp->cbs != NULL && bp->cbs->on_install != NULL)
 | ||||||
|  | +		(bp->cbs->on_install)(bp, proc);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  int | ||||||
|  |  breakpoint_get_return_bp(struct breakpoint **ret, | ||||||
|  |  			 struct breakpoint *bp, struct process *proc) | ||||||
|  | @@ -229,6 +237,7 @@ breakpoint_turn_on(struct breakpoint *bp, struct process *proc)
 | ||||||
|  |  	if (bp->enabled == 1) { | ||||||
|  |  		assert(proc->pid != 0); | ||||||
|  |  		enable_breakpoint(proc, bp); | ||||||
|  | +		breakpoint_on_install(bp, proc);
 | ||||||
|  |  	} | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  | -- 
 | ||||||
|  | 1.7.6.5 | ||||||
|  | 
 | ||||||
							
								
								
									
										36
									
								
								SOURCES/ltrace-0.7.91-cant_open.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								SOURCES/ltrace-0.7.91-cant_open.patch
									
									
									
									
									
										Normal 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(<e, command);
 | ||||||
|  | -		ltelf_destroy(<e);
 | ||||||
|  | +		{
 | ||||||
|  | +			struct ltelf lte;
 | ||||||
|  | +			if (ltelf_init(<e, command) == 0)
 | ||||||
|  | +				ltelf_destroy(<e);
 | ||||||
|  | +			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); | ||||||
|  |   | ||||||
							
								
								
									
										121
									
								
								SOURCES/ltrace-0.7.91-cet.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								SOURCES/ltrace-0.7.91-cet.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,121 @@ | |||||||
|  | diff -rup a/ltrace-elf.c b/ltrace-elf.c
 | ||||||
|  | --- a/ltrace-elf.c	2019-02-28 17:32:49.873659818 -0500
 | ||||||
|  | +++ b/ltrace-elf.c	2019-02-28 17:36:32.426779439 -0500
 | ||||||
|  | @@ -639,7 +639,21 @@ ltelf_read_elf(struct ltelf *lte, const
 | ||||||
|  |  			} | ||||||
|  |  		} else if (shdr.sh_type == SHT_PROGBITS | ||||||
|  |  			   || shdr.sh_type == SHT_NOBITS) { | ||||||
|  | -			if (strcmp(name, ".plt") == 0) {
 | ||||||
|  | +			if (strcmp(name, ".plt") == 0
 | ||||||
|  | +			    && lte->second_plt_seen == 0) {
 | ||||||
|  | +				lte->plt_addr = shdr.sh_addr;
 | ||||||
|  | +				lte->plt_size = shdr.sh_size;
 | ||||||
|  | +				lte->plt_data = elf_loaddata(scn, &shdr);
 | ||||||
|  | +				if (lte->plt_data == NULL)
 | ||||||
|  | +					fprintf(stderr,
 | ||||||
|  | +						"Can't load .plt data\n");
 | ||||||
|  | +				lte->plt_flags = shdr.sh_flags;
 | ||||||
|  | +			}
 | ||||||
|  | +			/* An Intel CET binary has two PLTs; the
 | ||||||
|  | +			   initial PLTGOT points to the second
 | ||||||
|  | +			   one.  */
 | ||||||
|  | +			else if (strcmp(name, ".plt.sec") == 0) {
 | ||||||
|  | +				lte->second_plt_seen = 1;
 | ||||||
|  |  				lte->plt_addr = shdr.sh_addr; | ||||||
|  |  				lte->plt_size = shdr.sh_size; | ||||||
|  |  				lte->plt_data = elf_loaddata(scn, &shdr); | ||||||
|  | diff -rup a/ltrace-elf.h b/ltrace-elf.h
 | ||||||
|  | --- a/ltrace-elf.h	2019-02-28 17:32:49.874660328 -0500
 | ||||||
|  | +++ b/ltrace-elf.h	2019-02-28 17:36:32.428779868 -0500
 | ||||||
|  | @@ -45,6 +45,7 @@ struct ltelf {
 | ||||||
|  |  	Elf_Data *dynsym; | ||||||
|  |  	size_t dynsym_count; | ||||||
|  |  	const char *dynstr; | ||||||
|  | +	int second_plt_seen;
 | ||||||
|  |  	GElf_Addr plt_addr; | ||||||
|  |  	GElf_Word plt_flags; | ||||||
|  |  	size_t plt_size; | ||||||
|  | diff -rup a/sysdeps/linux-gnu/x86/plt.c b/sysdeps/linux-gnu/x86/plt.c
 | ||||||
|  | --- a/sysdeps/linux-gnu/x86/plt.c	2019-02-28 17:32:49.991720041 -0500
 | ||||||
|  | +++ b/sysdeps/linux-gnu/x86/plt.c	2019-02-28 17:36:32.429780083 -0500
 | ||||||
|  | @@ -28,18 +28,18 @@
 | ||||||
|  |  #include "trace.h" | ||||||
|  |   | ||||||
|  |  static GElf_Addr | ||||||
|  | -x86_plt_offset(uint32_t i)
 | ||||||
|  | +x86_plt_offset(struct ltelf *lte, uint32_t i)
 | ||||||
|  |  { | ||||||
|  |  	/* Skip the first PLT entry, which contains a stub to call the | ||||||
|  |  	 * resolver.  */ | ||||||
|  | -	return (i + 1) * 16;
 | ||||||
|  | +	return (i + (lte->second_plt_seen ? 0 : 1)) * 16;
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  GElf_Addr | ||||||
|  |  arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela) | ||||||
|  |  { | ||||||
|  |  	uint32_t i = *VECT_ELEMENT(<e->arch.plt_map, uint32_t, ndx); | ||||||
|  | -	return x86_plt_offset(i) + lte->plt_addr;
 | ||||||
|  | +	return x86_plt_offset(lte, i) + lte->plt_addr;
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  void * | ||||||
|  | @@ -116,6 +116,13 @@ arch_elf_init(struct ltelf *lte, struct
 | ||||||
|  |  	 *	 400426:   68 00 00 00 00          pushq  $0x0 | ||||||
|  |  	 *	 40042b:   e9 e0 ff ff ff          jmpq   400410 <_init+0x18> | ||||||
|  |  	 * | ||||||
|  | +	 * For CET binaries it is the following:
 | ||||||
|  | +	 *
 | ||||||
|  | +	 *	13d0:       f3 0f 1e fa             endbr64 
 | ||||||
|  | +	 *	13d4:       68 27 00 00 00          pushq  $0x27  <-- index
 | ||||||
|  | +	 *	13d9:       f2 e9 71 fd ff ff       bnd jmpq 1150 <.plt>
 | ||||||
|  | +	 *	13df:       90                      nop
 | ||||||
|  | +	 *
 | ||||||
|  |           * 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 | ||||||
|  | @@ -128,11 +135,33 @@ arch_elf_init(struct ltelf *lte, struct
 | ||||||
|  |  	unsigned int i, sz = vect_size(<e->plt_relocs); | ||||||
|  |  	for (i = 0; i < sz; ++i) { | ||||||
|  |   | ||||||
|  | -		GElf_Addr offset = x86_plt_offset(i);
 | ||||||
|  | +		GElf_Addr offset = x86_plt_offset(lte, i);
 | ||||||
|  | +		uint32_t reloc_arg;
 | ||||||
|  |   | ||||||
|  |  		uint8_t byte; | ||||||
|  | -		if (elf_read_next_u8(lte->plt_data, &offset, &byte) < 0
 | ||||||
|  | -		    || byte != 0xff
 | ||||||
|  | +		if (elf_read_next_u8(lte->plt_data, &offset, &byte) < 0)
 | ||||||
|  | +		  continue;
 | ||||||
|  | +
 | ||||||
|  | +
 | ||||||
|  | +		if (byte == 0xf3
 | ||||||
|  | +		    && elf_read_next_u8(lte->plt_data, &offset, &byte) >= 0
 | ||||||
|  | +		    && byte == 0x0f
 | ||||||
|  | +		    && elf_read_next_u8(lte->plt_data, &offset, &byte) >= 0
 | ||||||
|  | +		    && byte == 0x1e
 | ||||||
|  | +		    && elf_read_next_u8(lte->plt_data, &offset, &byte) >= 0
 | ||||||
|  | +		    && byte == 0xfa
 | ||||||
|  | +		    && elf_read_next_u8(lte->plt_data, &offset, &byte) >= 0
 | ||||||
|  | +		    && byte == 0x68
 | ||||||
|  | +		    && elf_read_next_u32(lte->plt_data,
 | ||||||
|  | +					 &offset, &reloc_arg) >= 0)
 | ||||||
|  | +		  {
 | ||||||
|  | +		    /* CET */
 | ||||||
|  | +		    fprintf(stderr, "%d: reloc_arg is %lx\n", i, (long)reloc_arg);
 | ||||||
|  | +		    *VECT_ELEMENT(<e->arch.plt_map, unsigned int, reloc_arg) = i;
 | ||||||
|  | +		    continue;
 | ||||||
|  | +		  }
 | ||||||
|  | +
 | ||||||
|  | +		if (byte != 0xff
 | ||||||
|  |  		    || elf_read_next_u8(lte->plt_data, &offset, &byte) < 0 | ||||||
|  |  		    || (byte != 0xa3 && byte != 0x25)) | ||||||
|  |  			continue; | ||||||
|  | @@ -140,7 +169,6 @@ arch_elf_init(struct ltelf *lte, struct
 | ||||||
|  |  		/* 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, | ||||||
							
								
								
									
										45
									
								
								SOURCES/ltrace-0.7.91-man.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								SOURCES/ltrace-0.7.91-man.patch
									
									
									
									
									
										Normal 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 | ||||||
							
								
								
									
										175
									
								
								SOURCES/ltrace-0.7.91-multithread-no-f-1.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								SOURCES/ltrace-0.7.91-multithread-no-f-1.patch
									
									
									
									
									
										Normal 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~ | ||||||
							
								
								
									
										50
									
								
								SOURCES/ltrace-0.7.91-multithread-no-f-2.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								SOURCES/ltrace-0.7.91-multithread-no-f-2.patch
									
									
									
									
									
										Normal 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 | ||||||
							
								
								
									
										14
									
								
								SOURCES/ltrace-0.7.91-null.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								SOURCES/ltrace-0.7.91-null.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | diff --git a/output.c b/output.c
 | ||||||
|  | index 7cab383..18f9cf0 100644
 | ||||||
|  | --- a/output.c
 | ||||||
|  | +++ b/output.c
 | ||||||
|  | @@ -598,6 +598,9 @@ frame_callback (Dwfl_Frame *state, void *arg)
 | ||||||
|  |  					   NULL, NULL, NULL); | ||||||
|  |  		symname = dwfl_module_addrinfo(mod, pc, &off, &sym, | ||||||
|  |  					       NULL, NULL, NULL); | ||||||
|  | +	} else {
 | ||||||
|  | +		modname = "unknown";
 | ||||||
|  | +		symname = "unknown";
 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	/* This mimics the output produced by libunwind below.  */ | ||||||
							
								
								
									
										144
									
								
								SOURCES/ltrace-0.7.91-parser-ws_after_id.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								SOURCES/ltrace-0.7.91-parser-ws_after_id.patch
									
									
									
									
									
										Normal 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(¶m); | ||||||
|  | -				if (prototype_push_param(&fun, ¶m) < 0)
 | ||||||
|  | -					goto oom;
 | ||||||
|  | +				if (prototype_push_param(&fun, ¶m) < 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 | ||||||
|  | 
 | ||||||
							
								
								
									
										91
									
								
								SOURCES/ltrace-0.7.91-ppc-bias.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								SOURCES/ltrace-0.7.91-ppc-bias.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,91 @@ | |||||||
|  | diff --git a/sysdeps/linux-gnu/ppc/plt.c b/sysdeps/linux-gnu/ppc/plt.c
 | ||||||
|  | index 45ed7fb..5f81889 100644
 | ||||||
|  | --- a/sysdeps/linux-gnu/ppc/plt.c
 | ||||||
|  | +++ b/sysdeps/linux-gnu/ppc/plt.c
 | ||||||
|  | @@ -274,14 +274,15 @@ arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela)
 | ||||||
|  |   | ||||||
|  |  		assert(rela->r_addend != 0); | ||||||
|  |  		/* XXX double cast */ | ||||||
|  | -		arch_addr_t res_addr = (arch_addr_t) (uintptr_t) rela->r_addend;
 | ||||||
|  | +		arch_addr_t res_addr
 | ||||||
|  | +		  = (arch_addr_t) (uintptr_t) (rela->r_addend + lte->bias);
 | ||||||
|  |  		if (arch_translate_address(lte, res_addr, &res_addr) < 0) { | ||||||
|  |  			fprintf(stderr, "Couldn't OPD-translate IRELATIVE " | ||||||
|  |  				"resolver address.\n"); | ||||||
|  |  			return 0; | ||||||
|  |  		} | ||||||
|  |  		/* XXX double cast */ | ||||||
|  | -		return (GElf_Addr) (uintptr_t) res_addr;
 | ||||||
|  | +		return (GElf_Addr) (uintptr_t) (res_addr - lte->bias);
 | ||||||
|  |   | ||||||
|  |  	} else { | ||||||
|  |  		/* We put brakpoints to PLT entries the same as the | ||||||
|  | @@ -453,7 +454,7 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
 | ||||||
|  |  #ifndef EF_PPC64_ABI | ||||||
|  |  	assert (! (lte->ehdr.e_flags & 3 ) == 2) | ||||||
|  |  #else | ||||||
|  | -	lte->arch.elfv2_abi=((lte->ehdr.e_flags & EF_PPC64_ABI) == 2) ;
 | ||||||
|  | +	lte->arch.elfv2_abi = ((lte->ehdr.e_flags & EF_PPC64_ABI) == 2);
 | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  |  	if (lte->ehdr.e_machine == EM_PPC64 | ||||||
|  | @@ -827,15 +828,15 @@ arch_elf_add_plt_entry(struct process *proc, struct ltelf *lte,
 | ||||||
|  |  	assert(plt_slot_addr >= lte->plt_addr | ||||||
|  |  	       || plt_slot_addr < lte->plt_addr + lte->plt_size); | ||||||
|  |   | ||||||
|  | +	plt_entry_addr += lte->bias;
 | ||||||
|  | +	plt_slot_addr += lte->bias;
 | ||||||
|  | +
 | ||||||
|  |  	/* Should avoid to do read if dynamic linker hasn't run yet | ||||||
|  |  	 * or allow -1 a valid return code.  */ | ||||||
|  |  	GElf_Addr plt_slot_value; | ||||||
|  | -	if (read_plt_slot_value(proc, plt_slot_addr, &plt_slot_value) < 0) {
 | ||||||
|  | -		if (!lte->arch.elfv2_abi)
 | ||||||
|  | -			goto fail;
 | ||||||
|  | -		else
 | ||||||
|  | -			return PPC_PLT_UNRESOLVED;
 | ||||||
|  | -	}
 | ||||||
|  | +	int rc = read_plt_slot_value(proc, plt_slot_addr, &plt_slot_value);
 | ||||||
|  | +	if (rc < 0 && !lte->arch.elfv2_abi)
 | ||||||
|  | +		goto fail;
 | ||||||
|  |   | ||||||
|  |  	struct library_symbol *libsym = malloc(sizeof(*libsym)); | ||||||
|  |  	if (libsym == NULL) { | ||||||
|  | @@ -854,8 +855,9 @@ arch_elf_add_plt_entry(struct process *proc, struct ltelf *lte,
 | ||||||
|  |  		goto fail2; | ||||||
|  |  	libsym->arch.plt_slot_addr = plt_slot_addr; | ||||||
|  |   | ||||||
|  | -	if (! is_irelative
 | ||||||
|  | -	    && (plt_slot_value == plt_entry_addr || plt_slot_value == 0)) {
 | ||||||
|  | +	if (rc < 0 || (! is_irelative
 | ||||||
|  | +		       && (plt_slot_value == plt_entry_addr
 | ||||||
|  | +			   || plt_slot_value == 0))) {
 | ||||||
|  |  		libsym->arch.type = PPC_PLT_UNRESOLVED; | ||||||
|  |  		libsym->arch.resolved_value = plt_entry_addr; | ||||||
|  |  	} else { | ||||||
|  | @@ -1166,8 +1168,8 @@ ppc_plt_bp_install(struct breakpoint *bp, struct process *proc)
 | ||||||
|  |  				libsym->arch.resolved_value = plt_entry_addr; | ||||||
|  |  			} | ||||||
|  |  		} else { | ||||||
|  | -			fprintf(stderr, "Couldn't unresolve %s@%p.  Not tracing"
 | ||||||
|  | -				" this symbol.\n",
 | ||||||
|  | +			fprintf(stderr, "Couldn't unresolve %s@%p.  Will not"
 | ||||||
|  | +				" trace this symbol.\n",
 | ||||||
|  |  				breakpoint_name(bp), bp->addr); | ||||||
|  |  			proc_remove_breakpoint(proc, bp); | ||||||
|  |  		} | ||||||
|  | @@ -1222,6 +1224,14 @@ arch_library_symbol_clone(struct library_symbol *retp,
 | ||||||
|  |  			  struct library_symbol *libsym) | ||||||
|  |  { | ||||||
|  |  	retp->arch = libsym->arch; | ||||||
|  | +	if (libsym->arch.type == PPC_PLT_NEED_UNRESOLVE) {
 | ||||||
|  | +		assert(libsym->arch.data->self == libsym->arch.data);
 | ||||||
|  | +		retp->arch.data = malloc(sizeof *retp->arch.data);
 | ||||||
|  | +		if (retp->arch.data == NULL)
 | ||||||
|  | +			return -1;
 | ||||||
|  | +		*retp->arch.data = *libsym->arch.data;
 | ||||||
|  | +		retp->arch.data->self = retp->arch.data;
 | ||||||
|  | +	}
 | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
							
								
								
									
										52
									
								
								SOURCES/ltrace-0.7.91-ppc64-fork.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								SOURCES/ltrace-0.7.91-ppc64-fork.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | |||||||
|  | From 35742523e3daa0e59de0c1c3fdd8e5ff52891967 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Petr Machata <pmachata@redhat.com> | ||||||
|  | Date: Thu, 9 Jan 2014 23:41:50 +0100 | ||||||
|  | Subject: [PATCH] Fix a problem in tracing across fork on PPC64 | ||||||
|  | 
 | ||||||
|  | In order to avoid single-stepping through large portions of the | ||||||
|  | dynamic linker, ltrace remembers at which address the instruction that | ||||||
|  | resolved a PLT slot is.  It then puts a breakpoint to this address so | ||||||
|  | that it can fast-forward to that address next time it needs to catch a | ||||||
|  | PLT slot being resolved. | ||||||
|  | 
 | ||||||
|  | When a process is cloned, the pointer to this breakpoint is simply | ||||||
|  | copied over to the new process, instead of being looked up in the new | ||||||
|  | process structures.  This patches fixes this. | ||||||
|  | ---
 | ||||||
|  |  sysdeps/linux-gnu/ppc/plt.c |   14 +++++++++++++- | ||||||
|  |  1 files changed, 13 insertions(+), 1 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/sysdeps/linux-gnu/ppc/plt.c b/sysdeps/linux-gnu/ppc/plt.c
 | ||||||
|  | index 3ec1397..8715da6 100644
 | ||||||
|  | --- a/sysdeps/linux-gnu/ppc/plt.c
 | ||||||
|  | +++ b/sysdeps/linux-gnu/ppc/plt.c
 | ||||||
|  | @@ -1,6 +1,6 @@
 | ||||||
|  |  /* | ||||||
|  |   * 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.
 | ||||||
|  |   * Copyright (C) 2004,2008,2009 Juan Cespedes | ||||||
|  |   * Copyright (C) 2006 Paul Gilliam | ||||||
|  |   * | ||||||
|  | @@ -1157,6 +1157,18 @@ int
 | ||||||
|  |  arch_process_clone(struct process *retp, struct process *proc) | ||||||
|  |  { | ||||||
|  |  	retp->arch = proc->arch; | ||||||
|  | +
 | ||||||
|  | +	if (retp->arch.dl_plt_update_bp != NULL) {
 | ||||||
|  | +		/* Point it to the corresponding breakpoint in RETP.
 | ||||||
|  | +		 * It must be there, this part of PROC has already
 | ||||||
|  | +		 * been cloned to RETP.  */
 | ||||||
|  | +		retp->arch.dl_plt_update_bp
 | ||||||
|  | +			= address2bpstruct(retp,
 | ||||||
|  | +					   retp->arch.dl_plt_update_bp->addr);
 | ||||||
|  | +
 | ||||||
|  | +		assert(retp->arch.dl_plt_update_bp != NULL);
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 1.7.6.5 | ||||||
|  | 
 | ||||||
							
								
								
									
										221
									
								
								SOURCES/ltrace-0.7.91-ppc64-unprelink.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										221
									
								
								SOURCES/ltrace-0.7.91-ppc64-unprelink.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,221 @@ | |||||||
|  | From a0093ca43cf40d7e5f6cebeb64156062d2de46d9 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Petr Machata <pmachata@redhat.com> | ||||||
|  | Date: Fri, 10 Jan 2014 20:06:51 +0100 | ||||||
|  | Subject: [PATCH 2/2] Don't crash untraced calls via PLT in prelinked PPC64 | ||||||
|  |  binaries | ||||||
|  | 
 | ||||||
|  | In prelinked binaries, ltrace has to unprelinks PLT slots in order to | ||||||
|  | catch calls done through PLT.  This makes the calls done through these | ||||||
|  | slots invalid, because the special first PLT slot is not initialized, | ||||||
|  | and dynamic linker SIGSEGVs because of this.  Ltrace relies on | ||||||
|  | arranging breakpoints such that the dynamic linker is not actually | ||||||
|  | entered, and moves PC around itself to simulate the effects of a call | ||||||
|  | through PLT. | ||||||
|  | 
 | ||||||
|  | Originally, arch_elf_add_plt_entry was called only for symbols that | ||||||
|  | were actually traced.  Later this was changed and it's now called for | ||||||
|  | all PLT entries, and the resulting candidate list is filtered | ||||||
|  | afterwards.  This gives backends a chance to rename the symbol, as is | ||||||
|  | useful with IRELATIVE PLT calls, where symbol name may not be | ||||||
|  | available at all.  But the PPC backend was never updated to reflect | ||||||
|  | this, and unresolved all symbols for which arch_elf_add_plt_entry was | ||||||
|  | called, thus rendering _all_ PLT slots invalid, even those that | ||||||
|  | weren't later procted by breakpoints.  Thus calls done through any | ||||||
|  | untraced slots failed. | ||||||
|  | 
 | ||||||
|  | This patch fixes this problem by deferring the unprelinking of PLT | ||||||
|  | slots into the on_install hook of breakpoints. | ||||||
|  | ---
 | ||||||
|  |  sysdeps/linux-gnu/ppc/arch.h |   21 ++++++++- | ||||||
|  |  sysdeps/linux-gnu/ppc/plt.c  |   94 +++++++++++++++++++++++++++++++++-------- | ||||||
|  |  2 files changed, 94 insertions(+), 21 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/sysdeps/linux-gnu/ppc/arch.h b/sysdeps/linux-gnu/ppc/arch.h
 | ||||||
|  | index 2add3b8..bf9b5dc 100644
 | ||||||
|  | --- a/sysdeps/linux-gnu/ppc/arch.h
 | ||||||
|  | +++ b/sysdeps/linux-gnu/ppc/arch.h
 | ||||||
|  | @@ -1,6 +1,6 @@
 | ||||||
|  |  /* | ||||||
|  |   * This file is part of ltrace. | ||||||
|  | - * Copyright (C) 2012,2013 Petr Machata
 | ||||||
|  | + * Copyright (C) 2012,2013,2014 Petr Machata
 | ||||||
|  |   * Copyright (C) 2006 Paul Gilliam | ||||||
|  |   * Copyright (C) 2002,2004 Juan Cespedes | ||||||
|  |   * | ||||||
|  | @@ -87,12 +87,29 @@ enum ppc64_plt_type {
 | ||||||
|  |  	/* Very similar to PPC_PLT_UNRESOLVED, but for JMP_IREL | ||||||
|  |  	 * slots.  */ | ||||||
|  |  	PPC_PLT_IRELATIVE, | ||||||
|  | +
 | ||||||
|  | +	/* Transitional state before the breakpoint is enabled.  */
 | ||||||
|  | +	PPC_PLT_NEED_UNRESOLVE,
 | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  #define ARCH_HAVE_LIBRARY_SYMBOL_DATA | ||||||
|  | +struct ppc_unresolve_data;
 | ||||||
|  |  struct arch_library_symbol_data { | ||||||
|  |  	enum ppc64_plt_type type; | ||||||
|  | -	GElf_Addr resolved_value;
 | ||||||
|  | +
 | ||||||
|  | +	/* State		Contents
 | ||||||
|  | +	 *
 | ||||||
|  | +	 * PPC_DEFAULT		N/A
 | ||||||
|  | +	 * PPC64_PLT_STUB	N/A
 | ||||||
|  | +	 * PPC_PLT_UNRESOLVED	PLT entry address.
 | ||||||
|  | +	 * PPC_PLT_IRELATIVE	Likewise.
 | ||||||
|  | +	 * PPC_PLT_RESOLVED	The original value the slot was resolved to.
 | ||||||
|  | +	 * PPC_PLT_NEED_UNRESOLVE	DATA.
 | ||||||
|  | +	 */
 | ||||||
|  | +	union {
 | ||||||
|  | +		GElf_Addr resolved_value;
 | ||||||
|  | +		struct ppc_unresolve_data *data;
 | ||||||
|  | +	};
 | ||||||
|  |   | ||||||
|  |  	/* Address of corresponding slot in .plt.  */ | ||||||
|  |  	GElf_Addr plt_slot_addr; | ||||||
|  | diff --git a/sysdeps/linux-gnu/ppc/plt.c b/sysdeps/linux-gnu/ppc/plt.c
 | ||||||
|  | index 8715da6..332daa8 100644
 | ||||||
|  | --- a/sysdeps/linux-gnu/ppc/plt.c
 | ||||||
|  | +++ b/sysdeps/linux-gnu/ppc/plt.c
 | ||||||
|  | @@ -679,6 +679,14 @@ arch_elf_add_func_entry(struct process *proc, struct ltelf *lte,
 | ||||||
|  |  	return PLT_OK; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +struct ppc_unresolve_data {
 | ||||||
|  | +	struct ppc_unresolve_data *self; /* A canary.  */
 | ||||||
|  | +	GElf_Addr plt_entry_addr;
 | ||||||
|  | +	GElf_Addr plt_slot_addr;
 | ||||||
|  | +	GElf_Addr plt_slot_value;
 | ||||||
|  | +	bool is_irelative;
 | ||||||
|  | +};
 | ||||||
|  | +
 | ||||||
|  |  enum plt_status | ||||||
|  |  arch_elf_add_plt_entry(struct process *proc, struct ltelf *lte, | ||||||
|  |  		       const char *a_name, GElf_Rela *rela, size_t ndx, | ||||||
|  | @@ -778,28 +786,23 @@ arch_elf_add_plt_entry(struct process *proc, struct ltelf *lte,
 | ||||||
|  |  	    && (plt_slot_value == plt_entry_addr || plt_slot_value == 0)) { | ||||||
|  |  		libsym->arch.type = PPC_PLT_UNRESOLVED; | ||||||
|  |  		libsym->arch.resolved_value = plt_entry_addr; | ||||||
|  | -
 | ||||||
|  |  	} else { | ||||||
|  | -		/* Unresolve the .plt slot.  If the binary was
 | ||||||
|  | -		 * prelinked, this makes the code invalid, because in
 | ||||||
|  | -		 * case of prelinked binary, the dynamic linker
 | ||||||
|  | -		 * doesn't update .plt[0] and .plt[1] with addresses
 | ||||||
|  | -		 * of the resover.  But we don't care, we will never
 | ||||||
|  | -		 * need to enter the resolver.  That just means that
 | ||||||
|  | -		 * we have to un-un-resolve this back before we
 | ||||||
|  | -		 * detach.  */
 | ||||||
|  | -
 | ||||||
|  | -		if (unresolve_plt_slot(proc, plt_slot_addr, plt_entry_addr) < 0) {
 | ||||||
|  | -			library_symbol_destroy(libsym);
 | ||||||
|  | +		/* Mark the symbol for later unresolving.  We may not
 | ||||||
|  | +		 * do this right away, as this is called by ltrace
 | ||||||
|  | +		 * core for all symbols, and only later filtered.  We
 | ||||||
|  | +		 * only unresolve the symbol before the breakpoint is
 | ||||||
|  | +		 * enabled.  */
 | ||||||
|  | +
 | ||||||
|  | +		libsym->arch.type = PPC_PLT_NEED_UNRESOLVE;
 | ||||||
|  | +		libsym->arch.data = malloc(sizeof *libsym->arch.data);
 | ||||||
|  | +		if (libsym->arch.data == NULL)
 | ||||||
|  |  			goto fail2; | ||||||
|  | -		}
 | ||||||
|  |   | ||||||
|  | -		if (! is_irelative) {
 | ||||||
|  | -			mark_as_resolved(libsym, plt_slot_value);
 | ||||||
|  | -		} else {
 | ||||||
|  | -			libsym->arch.type = PPC_PLT_IRELATIVE;
 | ||||||
|  | -			libsym->arch.resolved_value = plt_entry_addr;
 | ||||||
|  | -		}
 | ||||||
|  | +		libsym->arch.data->self = libsym->arch.data;
 | ||||||
|  | +		libsym->arch.data->plt_entry_addr = plt_entry_addr;
 | ||||||
|  | +		libsym->arch.data->plt_slot_addr = plt_slot_addr;
 | ||||||
|  | +		libsym->arch.data->plt_slot_value = plt_slot_value;
 | ||||||
|  | +		libsym->arch.data->is_irelative = is_irelative;
 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	*ret = libsym; | ||||||
|  | @@ -999,6 +1002,7 @@ ppc_plt_bp_continue(struct breakpoint *bp, struct process *proc)
 | ||||||
|  |  		return; | ||||||
|  |   | ||||||
|  |  	case PPC64_PLT_STUB: | ||||||
|  | +	case PPC_PLT_NEED_UNRESOLVE:
 | ||||||
|  |  		/* These should never hit here.  */ | ||||||
|  |  		break; | ||||||
|  |  	} | ||||||
|  | @@ -1050,6 +1054,52 @@ ppc_plt_bp_retract(struct breakpoint *bp, struct process *proc)
 | ||||||
|  |  	} | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static void
 | ||||||
|  | +ppc_plt_bp_install(struct breakpoint *bp, struct process *proc)
 | ||||||
|  | +{
 | ||||||
|  | +	/* This should not be an artificial breakpoint.  */
 | ||||||
|  | +	struct library_symbol *libsym = bp->libsym;
 | ||||||
|  | +	if (libsym == NULL)
 | ||||||
|  | +		libsym = bp->arch.irel_libsym;
 | ||||||
|  | +	assert(libsym != NULL);
 | ||||||
|  | +
 | ||||||
|  | +	if (libsym->arch.type == PPC_PLT_NEED_UNRESOLVE) {
 | ||||||
|  | +		/* Unresolve the .plt slot.  If the binary was
 | ||||||
|  | +		 * prelinked, this makes the code invalid, because in
 | ||||||
|  | +		 * case of prelinked binary, the dynamic linker
 | ||||||
|  | +		 * doesn't update .plt[0] and .plt[1] with addresses
 | ||||||
|  | +		 * of the resover.  But we don't care, we will never
 | ||||||
|  | +		 * need to enter the resolver.  That just means that
 | ||||||
|  | +		 * we have to un-un-resolve this back before we
 | ||||||
|  | +		 * detach.  */
 | ||||||
|  | +
 | ||||||
|  | +		struct ppc_unresolve_data *data = libsym->arch.data;
 | ||||||
|  | +		libsym->arch.data = NULL;
 | ||||||
|  | +		assert(data->self == data);
 | ||||||
|  | +
 | ||||||
|  | +		GElf_Addr plt_slot_addr = data->plt_slot_addr;
 | ||||||
|  | +		GElf_Addr plt_slot_value = data->plt_slot_value;
 | ||||||
|  | +		GElf_Addr plt_entry_addr = data->plt_entry_addr;
 | ||||||
|  | +
 | ||||||
|  | +		if (unresolve_plt_slot(proc, plt_slot_addr,
 | ||||||
|  | +				       plt_entry_addr) == 0) {
 | ||||||
|  | +			if (! data->is_irelative) {
 | ||||||
|  | +				mark_as_resolved(libsym, plt_slot_value);
 | ||||||
|  | +			} else {
 | ||||||
|  | +				libsym->arch.type = PPC_PLT_IRELATIVE;
 | ||||||
|  | +				libsym->arch.resolved_value = plt_entry_addr;
 | ||||||
|  | +			}
 | ||||||
|  | +		} else {
 | ||||||
|  | +			fprintf(stderr, "Couldn't unresolve %s@%p.  Not tracing"
 | ||||||
|  | +				" this symbol.\n",
 | ||||||
|  | +				breakpoint_name(bp), bp->addr);
 | ||||||
|  | +			proc_remove_breakpoint(proc, bp);
 | ||||||
|  | +		}
 | ||||||
|  | +
 | ||||||
|  | +		free(data);
 | ||||||
|  | +	}
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  int | ||||||
|  |  arch_library_init(struct library *lib) | ||||||
|  |  { | ||||||
|  | @@ -1080,6 +1130,11 @@ arch_library_symbol_init(struct library_symbol *libsym)
 | ||||||
|  |  void | ||||||
|  |  arch_library_symbol_destroy(struct library_symbol *libsym) | ||||||
|  |  { | ||||||
|  | +	if (libsym->arch.type == PPC_PLT_NEED_UNRESOLVE) {
 | ||||||
|  | +		assert(libsym->arch.data->self == libsym->arch.data);
 | ||||||
|  | +		free(libsym->arch.data);
 | ||||||
|  | +		libsym->arch.data = NULL;
 | ||||||
|  | +	}
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  int | ||||||
|  | @@ -1115,6 +1170,7 @@ arch_breakpoint_init(struct process *proc, struct breakpoint *bp)
 | ||||||
|  |  	static struct bp_callbacks cbs = { | ||||||
|  |  		.on_continue = ppc_plt_bp_continue, | ||||||
|  |  		.on_retract = ppc_plt_bp_retract, | ||||||
|  | +		.on_install = ppc_plt_bp_install,
 | ||||||
|  |  	}; | ||||||
|  |  	breakpoint_set_callbacks(bp, &cbs); | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 1.7.6.5 | ||||||
|  | 
 | ||||||
							
								
								
									
										44
									
								
								SOURCES/ltrace-0.7.91-ppc64le-configure.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								SOURCES/ltrace-0.7.91-ppc64le-configure.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | |||||||
|  | From eea6091f8672b01f7f022b0fc367e0f568225ffc Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Petr Machata <pmachata@redhat.com> | ||||||
|  | Date: Fri, 8 Aug 2014 17:09:58 +0200 | ||||||
|  | Subject: [PATCH] Recognize powerpc64le in configure | ||||||
|  | 
 | ||||||
|  | ---
 | ||||||
|  |  configure.ac | 14 +++++++------- | ||||||
|  |  1 file changed, 7 insertions(+), 7 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/configure.ac b/configure.ac
 | ||||||
|  | index 4f360c8..6fe5e3b 100644
 | ||||||
|  | --- a/configure.ac
 | ||||||
|  | +++ b/configure.ac
 | ||||||
|  | @@ -43,7 +43,7 @@ case "${host_cpu}" in
 | ||||||
|  |      arm*|sa110)		HOST_CPU="arm" ;; | ||||||
|  |      cris*)		HOST_CPU="cris" ;; | ||||||
|  |      mips*)		HOST_CPU="mips" ;; | ||||||
|  | -    powerpc|powerpc64)	HOST_CPU="ppc" ;;
 | ||||||
|  | +    powerpc|powerpc64|powerpc64le)	HOST_CPU="ppc" ;;
 | ||||||
|  |      sun4u|sparc64)	HOST_CPU="sparc" ;; | ||||||
|  |      s390x)		HOST_CPU="s390" ;; | ||||||
|  |      i?86|x86_64)	HOST_CPU="x86" ;; | ||||||
|  | @@ -210,12 +210,12 @@ AC_MSG_RESULT([$enable_libunwind])
 | ||||||
|  |   | ||||||
|  |  if test x"$enable_libunwind" = xyes; then | ||||||
|  |    case "${host_cpu}" in | ||||||
|  | -      arm*|sa110)         UNWIND_ARCH="arm" ;;
 | ||||||
|  | -      i?86)               UNWIND_ARCH="x86" ;;
 | ||||||
|  | -      powerpc)            UNWIND_ARCH="ppc32" ;;
 | ||||||
|  | -      powerpc64)          UNWIND_ARCH="ppc64" ;;
 | ||||||
|  | -      mips*)              UNWIND_ARCH="mips" ;;
 | ||||||
|  | -      *)                  UNWIND_ARCH="${host_cpu}" ;;
 | ||||||
|  | +      arm*|sa110)	  UNWIND_ARCH="arm" ;;
 | ||||||
|  | +      i?86)		  UNWIND_ARCH="x86" ;;
 | ||||||
|  | +      powerpc)		  UNWIND_ARCH="ppc32" ;;
 | ||||||
|  | +      powerpc64|powerpc64le)	UNWIND_ARCH="ppc64" ;;
 | ||||||
|  | +      mips*)		  UNWIND_ARCH="mips" ;;
 | ||||||
|  | +      *)		  UNWIND_ARCH="${host_cpu}" ;;
 | ||||||
|  |    esac | ||||||
|  |   | ||||||
|  |    saved_LDFLAGS="${LDFLAGS}" | ||||||
|  | -- 
 | ||||||
|  | 2.1.0 | ||||||
|  | 
 | ||||||
							
								
								
									
										421
									
								
								SOURCES/ltrace-0.7.91-ppc64le-fixes.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										421
									
								
								SOURCES/ltrace-0.7.91-ppc64le-fixes.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,421 @@ | |||||||
|  | diff --git a/sysdeps/linux-gnu/ppc/arch.h b/sysdeps/linux-gnu/ppc/arch.h
 | ||||||
|  | index d5ad759..a8b67bb 100644
 | ||||||
|  | --- a/sysdeps/linux-gnu/ppc/arch.h
 | ||||||
|  | +++ b/sysdeps/linux-gnu/ppc/arch.h
 | ||||||
|  | @@ -32,36 +32,45 @@
 | ||||||
|  |  #define LT_ELF_MACHINE	EM_PPC | ||||||
|  |   | ||||||
|  |  #ifdef __powerpc64__ // Says 'ltrace' is 64 bits, says nothing about target. | ||||||
|  | -#define LT_ELFCLASS2	ELFCLASS64
 | ||||||
|  | -#define LT_ELF_MACHINE2	EM_PPC64
 | ||||||
|  | +# define LT_ELFCLASS2	ELFCLASS64
 | ||||||
|  | +# define LT_ELF_MACHINE2	EM_PPC64
 | ||||||
|  |   | ||||||
|  |  # ifdef __LITTLE_ENDIAN__ | ||||||
|  | -# define BREAKPOINT_VALUE { 0x08, 0x00, 0xe0, 0x7f }
 | ||||||
|  | -# define ARCH_ENDIAN_LITTLE
 | ||||||
|  | +#  define BREAKPOINT_VALUE { 0x08, 0x00, 0xe0, 0x7f }
 | ||||||
|  | +#  define ARCH_ENDIAN_LITTLE
 | ||||||
|  |  # else | ||||||
|  | -# define BREAKPOINT_VALUE { 0x7f, 0xe0, 0x00, 0x08 }
 | ||||||
|  | -# define ARCH_SUPPORTS_OPD
 | ||||||
|  | -# define ARCH_ENDIAN_BIG
 | ||||||
|  | +#  define BREAKPOINT_VALUE { 0x7f, 0xe0, 0x00, 0x08 }
 | ||||||
|  | +#  define ARCH_SUPPORTS_OPD
 | ||||||
|  | +#  define ARCH_ENDIAN_BIG
 | ||||||
|  |  # endif | ||||||
|  |   | ||||||
|  | -# if _CALL_ELF != 2
 | ||||||
|  | -# define ARCH_SUPPORTS_OPD
 | ||||||
|  | -# define STACK_FRAME_OVERHEAD 112
 | ||||||
|  | +# if !defined(_CALL_ELF) || _CALL_ELF < 2
 | ||||||
|  | +#  define ARCH_SUPPORTS_OPD
 | ||||||
|  | +#  define STACK_FRAME_OVERHEAD 112
 | ||||||
|  |  #  ifndef EF_PPC64_ABI | ||||||
|  | -#  define EF_PPC64_ABI 3
 | ||||||
|  | +#   define EF_PPC64_ABI 3
 | ||||||
|  |  #  endif | ||||||
|  | -# else /* _CALL_ELF == 2 ABIv2 */
 | ||||||
|  | -# define STACK_FRAME_OVERHEAD 32
 | ||||||
|  | +# elif _CALL_ELF == 2  /* ELFv2 ABI */
 | ||||||
|  | +#  define STACK_FRAME_OVERHEAD 32
 | ||||||
|  | +# else
 | ||||||
|  | +#  error Unsupported PowerPC64 ABI.
 | ||||||
|  |  # endif /* CALL_ELF */ | ||||||
|  |   | ||||||
|  |  #else | ||||||
|  | -#define BREAKPOINT_VALUE { 0x7f, 0xe0, 0x00, 0x08 }
 | ||||||
|  | -#define ARCH_ENDIAN_BIG
 | ||||||
|  | +# define STACK_FRAME_OVERHEAD 112
 | ||||||
|  | +# define BREAKPOINT_VALUE { 0x7f, 0xe0, 0x00, 0x08 }
 | ||||||
|  | +# define ARCH_ENDIAN_BIG
 | ||||||
|  |  # ifndef EF_PPC64_ABI | ||||||
|  | -# define EF_PPC64_ABI 3
 | ||||||
|  | +#  define EF_PPC64_ABI 3
 | ||||||
|  |  # endif | ||||||
|  |  #endif 	/* __powerpc64__ */ | ||||||
|  |   | ||||||
|  | +#ifdef _CALL_ELF
 | ||||||
|  | +enum { ppc64_call_elf_abi = _CALL_ELF };
 | ||||||
|  | +#else
 | ||||||
|  | +enum { ppc64_call_elf_abi = 0 };
 | ||||||
|  | +#endif
 | ||||||
|  | +
 | ||||||
|  |  #define ARCH_HAVE_SW_SINGLESTEP | ||||||
|  |  #define ARCH_HAVE_ADD_PLT_ENTRY | ||||||
|  |  #define ARCH_HAVE_ADD_FUNC_ENTRY | ||||||
|  | diff --git a/sysdeps/linux-gnu/ppc/fetch.c b/sysdeps/linux-gnu/ppc/fetch.c
 | ||||||
|  | index c9381c3..c6cbd71 100644
 | ||||||
|  | --- a/sysdeps/linux-gnu/ppc/fetch.c
 | ||||||
|  | +++ b/sysdeps/linux-gnu/ppc/fetch.c
 | ||||||
|  | @@ -1,6 +1,6 @@
 | ||||||
|  |  /* | ||||||
|  |   * This file is part of ltrace. | ||||||
|  | - * Copyright (C) 2012 Petr Machata, Red Hat Inc.
 | ||||||
|  | + * Copyright (C) 2012, 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 | ||||||
|  | @@ -23,6 +23,7 @@
 | ||||||
|  |  #include <stdlib.h> | ||||||
|  |  #include <string.h> | ||||||
|  |  #include <sys/ucontext.h> | ||||||
|  | +#include <stdio.h>
 | ||||||
|  |   | ||||||
|  |  #include "backend.h" | ||||||
|  |  #include "fetch.h" | ||||||
|  | @@ -57,7 +58,7 @@ struct fetch_context {
 | ||||||
|  |  	arch_addr_t stack_pointer; | ||||||
|  |  	int greg; | ||||||
|  |  	int freg; | ||||||
|  | -	int ret_struct;
 | ||||||
|  | +	bool ret_struct;
 | ||||||
|  |   | ||||||
|  |  	union { | ||||||
|  |  		gregs32_t r32; | ||||||
|  | @@ -65,11 +66,29 @@ struct fetch_context {
 | ||||||
|  |  	} regs; | ||||||
|  |  	struct fpregs_t fpregs; | ||||||
|  |  	int vgreg; | ||||||
|  | -	int struct_size;
 | ||||||
|  | -	int struct_hfa_size;
 | ||||||
|  | -	int struct_hfa_count;
 | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +static bool
 | ||||||
|  | +is_eligible_hfa(struct arg_type_info *info,
 | ||||||
|  | +		struct arg_type_info **hfa_infop, size_t *hfa_countp)
 | ||||||
|  | +{
 | ||||||
|  | +	size_t hfa_count;
 | ||||||
|  | +	struct arg_type_info *hfa_info = type_get_hfa_type(info, &hfa_count);
 | ||||||
|  | +
 | ||||||
|  | +	if (hfa_info != NULL && hfa_count <= 8
 | ||||||
|  | +	    && (hfa_info->type == ARGTYPE_FLOAT
 | ||||||
|  | +		|| hfa_info->type == ARGTYPE_DOUBLE)) {
 | ||||||
|  | +
 | ||||||
|  | +		if (hfa_infop != NULL)
 | ||||||
|  | +			*hfa_infop = hfa_info;
 | ||||||
|  | +		if (hfa_countp != NULL)
 | ||||||
|  | +			*hfa_countp = hfa_count;
 | ||||||
|  | +		return true;
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  | +	return false;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  static int | ||||||
|  |  fetch_context_init(struct process *proc, struct fetch_context *context) | ||||||
|  |  { | ||||||
|  | @@ -125,30 +144,37 @@ arch_fetch_arg_init(enum tof type, struct process *proc,
 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	context->vgreg = context->greg; | ||||||
|  | -	context->struct_size = 0;
 | ||||||
|  | -	context->struct_hfa_size = 0;
 | ||||||
|  | -	context->struct_hfa_count = 0;
 | ||||||
|  |   | ||||||
|  |  	/* Aggregates or unions of any length, and character strings | ||||||
|  |  	 * of length longer than 8 bytes, will be returned in a | ||||||
|  |  	 * storage buffer allocated by the caller. The caller will | ||||||
|  |  	 * pass the address of this buffer as a hidden first argument | ||||||
|  |  	 * in r3, causing the first explicit argument to be passed in | ||||||
|  | -	 * r4.  */
 | ||||||
|  | -	context->ret_struct = ret_info->type == ARGTYPE_STRUCT;
 | ||||||
|  | -	if (context->ret_struct) {
 | ||||||
|  | -#if _CALL_ELF == 2
 | ||||||
|  | -		/* if R3 points to stack, parameters will be in R4.  */
 | ||||||
|  | -		uint64_t pstack_end = ptrace(PTRACE_PEEKTEXT, proc->pid,
 | ||||||
|  | -					proc->stack_pointer, 0);
 | ||||||
|  | -		if (((arch_addr_t)context->regs.r64[3] > proc->stack_pointer)
 | ||||||
|  | -		    && (context->regs.r64[3] < pstack_end)) {
 | ||||||
|  | +	 * r4.
 | ||||||
|  | +	 */
 | ||||||
|  | +
 | ||||||
|  | +	context->ret_struct = false;
 | ||||||
|  | +
 | ||||||
|  | +	if (ppc64_call_elf_abi == 2) {
 | ||||||
|  | +		/* With ELFv2 ABI, aggregates that consist
 | ||||||
|  | +		 * (recursively) only of members of the same
 | ||||||
|  | +		 * floating-point or vector type, are passed in a
 | ||||||
|  | +		 * series of floating-point resp. vector registers.
 | ||||||
|  | +		 * Additionally, when returning any aggregate of up to
 | ||||||
|  | +		 * 16 bytes, general-purpose registers are used.  */
 | ||||||
|  | +
 | ||||||
|  | +		if (ret_info->type == ARGTYPE_STRUCT
 | ||||||
|  | +		    && ! is_eligible_hfa(ret_info, NULL, NULL)
 | ||||||
|  | +		    && type_sizeof(proc, ret_info) > 16) {
 | ||||||
|  | +
 | ||||||
|  | +			context->ret_struct = true;
 | ||||||
|  |  			context->greg++; | ||||||
|  |  			context->stack_pointer += 8; | ||||||
|  |  		} | ||||||
|  | -#else
 | ||||||
|  | +
 | ||||||
|  | +	} else if (ret_info->type == ARGTYPE_STRUCT) {
 | ||||||
|  | +		context->ret_struct = true;
 | ||||||
|  |  		context->greg++; | ||||||
|  | -#endif
 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	return context; | ||||||
|  | @@ -176,17 +202,16 @@ allocate_stack_slot(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |   | ||||||
|  |  	size_t a = type_alignof(proc, info); | ||||||
|  |  	size_t off = 0; | ||||||
|  | -	if (proc->e_machine == EM_PPC && a < 4)
 | ||||||
|  | -		a = 4;
 | ||||||
|  | -#if _CALL_ELF == 2
 | ||||||
|  | -	else if (proc->e_machine == EM_PPC64 && sz == 4 && is_hfa_type)
 | ||||||
|  | +	if (proc->e_machine == EM_PPC && a < 4) {
 | ||||||
|  |  		a = 4; | ||||||
|  | -	else
 | ||||||
|  | -		a = 8;
 | ||||||
|  | -#else
 | ||||||
|  | -	else if (proc->e_machine == EM_PPC64 && a < 8)
 | ||||||
|  | -#endif
 | ||||||
|  | +	} else if (ppc64_call_elf_abi == 2) {
 | ||||||
|  | +		if (proc->e_machine == EM_PPC64 && sz == 4 && is_hfa_type) {
 | ||||||
|  | +			a = 4;
 | ||||||
|  | +		} else
 | ||||||
|  | +			a = 8;
 | ||||||
|  | +	} else if (proc->e_machine == EM_PPC64 && a < 8) {
 | ||||||
|  |  		a = 8; | ||||||
|  | +	}
 | ||||||
|  |   | ||||||
|  |  	/* XXX Remove the two double casts when arch_addr_t | ||||||
|  |  	 * becomes integral type.  */ | ||||||
|  | @@ -259,18 +284,19 @@ allocate_gpr(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |  	if (sz == (size_t)-1) | ||||||
|  |  		return -1; | ||||||
|  |  	assert(sz == 1 || sz == 2 || sz == 4 || sz == 8); | ||||||
|  | -#if _CALL_ELF == 2
 | ||||||
|  | -	/* Consume the stack slot corresponding to this arg.  */
 | ||||||
|  | -	if ((sz + off) >= 8)
 | ||||||
|  | -		ctx->greg++;
 | ||||||
|  |   | ||||||
|  | -	if (is_hfa_type)
 | ||||||
|  | -		ctx->stack_pointer += sz;
 | ||||||
|  | -	else
 | ||||||
|  | -		ctx->stack_pointer += 8;
 | ||||||
|  | -#else
 | ||||||
|  | -	ctx->greg++;
 | ||||||
|  | -#endif
 | ||||||
|  | +	if (ppc64_call_elf_abi == 2) {
 | ||||||
|  | +		/* Consume the stack slot corresponding to this arg.  */
 | ||||||
|  | +		if ((sz + off) >= 8)
 | ||||||
|  | +			ctx->greg++;
 | ||||||
|  | +
 | ||||||
|  | +		if (is_hfa_type)
 | ||||||
|  | +			ctx->stack_pointer += sz;
 | ||||||
|  | +		else
 | ||||||
|  | +			ctx->stack_pointer += 8;
 | ||||||
|  | +	} else {
 | ||||||
|  | +		ctx->greg++;
 | ||||||
|  | +	}
 | ||||||
|  |   | ||||||
|  |  	if (valuep == NULL) | ||||||
|  |  		return 0; | ||||||
|  | @@ -326,7 +352,6 @@ allocate_float(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |  	return allocate_stack_slot(ctx, proc, info, valuep, is_hfa_type); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -#if _CALL_ELF == 2
 | ||||||
|  |  static int | ||||||
|  |  allocate_hfa(struct fetch_context *ctx, struct process *proc, | ||||||
|  |  	     struct arg_type_info *info, struct value *valuep, | ||||||
|  | @@ -336,27 +361,27 @@ allocate_hfa(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |  	if (sz == (size_t)-1) | ||||||
|  |  		return -1; | ||||||
|  |   | ||||||
|  | -	ctx->struct_hfa_size += sz;
 | ||||||
|  | -
 | ||||||
|  |  	/* There are two changes regarding structure return types: | ||||||
|  | -	 * * heterogeneous float/vector structs are returned
 | ||||||
|  | -	 *   in (multiple) FP/vector registers,
 | ||||||
|  | -	 *   instead of via implicit reference.
 | ||||||
|  | -	 * * small structs (up to 16 bytes) are return
 | ||||||
|  | -	 *   in one or two GPRs, instead of via implicit reference.
 | ||||||
|  | +	 * * heterogeneous float/vector structs are returned in
 | ||||||
|  | +	 *   (multiple) FP/vector registers, instead of via implicit
 | ||||||
|  | +	 *   reference.
 | ||||||
|  | +	 * * small structs (up to 16 bytes) are return in one or two
 | ||||||
|  | +	 *   GPRs, instead of via implicit reference.
 | ||||||
|  |  	 * | ||||||
|  |  	 * Other structures (larger than 16 bytes, not heterogeneous) | ||||||
|  |  	 * are still returned via implicit reference (i.e. a pointer | ||||||
|  |  	 * to memory where to return the struct being passed in r3). | ||||||
|  | -	 * Of course, whether or not an implicit reference pointer
 | ||||||
|  | -	 * is present will shift the remaining arguments,
 | ||||||
|  | -	 * so you need to get this right for ELFv2 in order
 | ||||||
|  | -	 * to get the arguments correct.
 | ||||||
|  | +	 * Of course, whether or not an implicit reference pointer is
 | ||||||
|  | +	 * present will shift the remaining arguments, so you need to
 | ||||||
|  | +	 * get this right for ELFv2 in order to get the arguments
 | ||||||
|  | +	 * correct.
 | ||||||
|  | +	 *
 | ||||||
|  |  	 * If an actual parameter is known to correspond to an HFA | ||||||
|  |  	 * formal parameter, each element is passed in the next | ||||||
|  |  	 * available floating-point argument register starting at fp1 | ||||||
|  |  	 * until the fp13. The remaining elements of the aggregate are | ||||||
|  | -	 * passed on the stack.  */
 | ||||||
|  | +	 * passed on the stack.
 | ||||||
|  | +	 */
 | ||||||
|  |  	size_t slot_off = 0; | ||||||
|  |   | ||||||
|  |  	unsigned char *buf = value_reserve(valuep, sz); | ||||||
|  | @@ -366,26 +391,17 @@ allocate_hfa(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |  	struct arg_type_info *hfa_info = type_get_simple(hfa_type); | ||||||
|  |  	size_t hfa_sz = type_sizeof(proc, hfa_info); | ||||||
|  |   | ||||||
|  | -	if (hfa_count > 8)
 | ||||||
|  | -		ctx->struct_hfa_count += hfa_count;
 | ||||||
|  | -
 | ||||||
|  |  	while (hfa_count > 0 && ctx->freg <= 13) { | ||||||
|  | -		int rc;
 | ||||||
|  |  		struct value tmp; | ||||||
|  | -
 | ||||||
|  |  		value_init(&tmp, proc, NULL, hfa_info, 0); | ||||||
|  | +		int rc = allocate_float(ctx, proc, hfa_info,
 | ||||||
|  | +					&tmp, slot_off, true);
 | ||||||
|  | +		if (rc == 0)
 | ||||||
|  | +			memcpy(buf, value_get_data(&tmp, NULL), hfa_sz);
 | ||||||
|  | +		value_destroy(&tmp);
 | ||||||
|  |   | ||||||
|  | -		/* Hetereogeneous struct - get value on GPR or stack.  */
 | ||||||
|  | -		if (((hfa_type == ARGTYPE_FLOAT
 | ||||||
|  | -		    || hfa_type == ARGTYPE_DOUBLE)
 | ||||||
|  | -		      && hfa_count <= 8))
 | ||||||
|  | -			rc = allocate_float(ctx, proc, hfa_info, &tmp,
 | ||||||
|  | -						slot_off, true);
 | ||||||
|  | -		else
 | ||||||
|  | -			rc = allocate_gpr(ctx, proc, hfa_info, &tmp,
 | ||||||
|  | -						slot_off, true);
 | ||||||
|  | -
 | ||||||
|  | -		memcpy(buf, value_get_data(&tmp, NULL), hfa_sz);
 | ||||||
|  | +		if (rc < 0)
 | ||||||
|  | +			return -1;
 | ||||||
|  |   | ||||||
|  |  		slot_off += hfa_sz; | ||||||
|  |  		buf += hfa_sz; | ||||||
|  | @@ -394,17 +410,13 @@ allocate_hfa(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |  			slot_off = 0; | ||||||
|  |  			ctx->vgreg++; | ||||||
|  |  		} | ||||||
|  | -
 | ||||||
|  | -		value_destroy(&tmp);
 | ||||||
|  | -		if (rc < 0)
 | ||||||
|  | -			return -1;
 | ||||||
|  |  	} | ||||||
|  |  	if (hfa_count == 0) | ||||||
|  |  		return 0; | ||||||
|  |   | ||||||
|  |  	/* if no remaining FP, GPR corresponding to slot is used | ||||||
|  | -	* Mostly it is in part of r10.  */
 | ||||||
|  | -	if (ctx->struct_hfa_size <= 64 && ctx->vgreg == 10) {
 | ||||||
|  | +	 * Mostly it is in part of r10.  */
 | ||||||
|  | +	if (ctx->vgreg == 10) {
 | ||||||
|  |  		while (ctx->vgreg <= 10) { | ||||||
|  |  			struct value tmp; | ||||||
|  |  			value_init(&tmp, proc, NULL, hfa_info, 0); | ||||||
|  | @@ -428,11 +440,8 @@ allocate_hfa(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |  		} | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	if (hfa_count == 0)
 | ||||||
|  | -		return 0;
 | ||||||
|  | -
 | ||||||
|  |  	/* Remaining values are on stack */ | ||||||
|  | -	while (hfa_count) {
 | ||||||
|  | +	while (hfa_count > 0) {
 | ||||||
|  |  		struct value tmp; | ||||||
|  |  		value_init(&tmp, proc, NULL, hfa_info, 0); | ||||||
|  |   | ||||||
|  | @@ -444,7 +453,6 @@ allocate_hfa(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |  	} | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  | -#endif
 | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  |  allocate_argument(struct fetch_context *ctx, struct process *proc, | ||||||
|  | @@ -459,24 +467,20 @@ allocate_argument(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |  	case ARGTYPE_FLOAT: | ||||||
|  |  	case ARGTYPE_DOUBLE: | ||||||
|  |  		return allocate_float(ctx, proc, info, valuep, | ||||||
|  | -					8 - type_sizeof(proc,info), false);
 | ||||||
|  | +				      8 - type_sizeof(proc,info), false);
 | ||||||
|  |   | ||||||
|  |  	case ARGTYPE_STRUCT: | ||||||
|  |  		if (proc->e_machine == EM_PPC) { | ||||||
|  |  			if (value_pass_by_reference(valuep) < 0) | ||||||
|  |  				return -1; | ||||||
|  | -		} else {
 | ||||||
|  | -#if _CALL_ELF == 2
 | ||||||
|  | +		} else if (ppc64_call_elf_abi == 2) {
 | ||||||
|  |  			struct arg_type_info *hfa_info; | ||||||
|  | -			size_t hfa_size;
 | ||||||
|  | -			hfa_info = type_get_hfa_type(info, &hfa_size);
 | ||||||
|  | -			if (hfa_info != NULL ) {
 | ||||||
|  | -				size_t sz = type_sizeof(proc, info);
 | ||||||
|  | -				ctx->struct_size += sz;
 | ||||||
|  | +			size_t hfa_count;
 | ||||||
|  | +			if (is_eligible_hfa(info, &hfa_info, &hfa_count)) {
 | ||||||
|  |  				return allocate_hfa(ctx, proc, info, valuep, | ||||||
|  | -						hfa_info->type, hfa_size);
 | ||||||
|  | +						hfa_info->type, hfa_count);
 | ||||||
|  |  			} | ||||||
|  | -#endif
 | ||||||
|  | +		} else {
 | ||||||
|  |  			/* PPC64: Fixed size aggregates and unions passed by | ||||||
|  |  			 * value are mapped to as many doublewords of the | ||||||
|  |  			 * parameter save area as the value uses in memory. | ||||||
|  | @@ -510,9 +514,6 @@ allocate_argument(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |  	if (sz == (size_t)-1) | ||||||
|  |  		return -1; | ||||||
|  |   | ||||||
|  | -	if (ctx->ret_struct)
 | ||||||
|  | -		ctx->struct_size += sz;
 | ||||||
|  | -
 | ||||||
|  |  	size_t slots = (sz + width - 1) / width;  /* Round up.  */ | ||||||
|  |  	unsigned char *buf = value_reserve(valuep, slots * width); | ||||||
|  |  	if (buf == NULL) | ||||||
|  | @@ -605,19 +606,7 @@ arch_fetch_retval(struct fetch_context *ctx, enum tof type,
 | ||||||
|  |  	if (fetch_context_init(proc, ctx) < 0) | ||||||
|  |  		return -1; | ||||||
|  |   | ||||||
|  | -#if _CALL_ELF == 2
 | ||||||
|  | -	void *ptr = (void *)(ctx->regs.r64[1]+32);
 | ||||||
|  | -	uint64_t val = ptrace(PTRACE_PEEKTEXT, proc->pid, ptr, 0);
 | ||||||
|  | -
 | ||||||
|  | -	if (ctx->ret_struct
 | ||||||
|  | -	   && ((ctx->struct_size > 64
 | ||||||
|  | -	      || ctx->struct_hfa_count > 8
 | ||||||
|  | -	      || (ctx->struct_hfa_size == 0 && ctx->struct_size > 56)
 | ||||||
|  | -	      || (ctx->regs.r64[3] == ctx->regs.r64[1]+32)
 | ||||||
|  | -	      || (ctx->regs.r64[3] == val )))) {
 | ||||||
|  | -#else
 | ||||||
|  |  	if (ctx->ret_struct) { | ||||||
|  | -#endif
 | ||||||
|  |  		assert(info->type == ARGTYPE_STRUCT); | ||||||
|  |   | ||||||
|  |  		uint64_t addr = read_gpr(ctx, proc, 3); | ||||||
							
								
								
									
										786
									
								
								SOURCES/ltrace-0.7.91-ppc64le-support.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										786
									
								
								SOURCES/ltrace-0.7.91-ppc64le-support.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,786 @@ | |||||||
|  | From eea4ad2cce289753aaa35b4e0258a76d8f8f367c Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Thierry Fauck <thierry@linux.vnet.ibm.com> | ||||||
|  | Date: Tue, 13 May 2014 07:48:24 -0400 | ||||||
|  | Subject: [PATCH] Support for powerpc64 arch ppc64el | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Thierry Fauck <thierry@linux.vnet.ibm.com> | ||||||
|  | 
 | ||||||
|  | 	Add support for ppc64le proc and ELF ABIv2. | ||||||
|  | 	Provides support for irelative and wchar | ||||||
|  | ---
 | ||||||
|  |  ltrace-elf.c                           |    2 +- | ||||||
|  |  ltrace-elf.h                           |    1 + | ||||||
|  |  sysdeps/linux-gnu/ppc/arch.h           |   35 ++++- | ||||||
|  |  sysdeps/linux-gnu/ppc/fetch.c          |  244 +++++++++++++++++++++++++++++--- | ||||||
|  |  sysdeps/linux-gnu/ppc/plt.c            |   98 ++++++++++++-- | ||||||
|  |  sysdeps/linux-gnu/ppc/trace.c          |   10 ++ | ||||||
|  |  testsuite/ltrace.main/system_calls.exp |    2 +- | ||||||
|  |  7 files changed, 356 insertions(+), 36 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/ltrace-elf.c b/ltrace-elf.c
 | ||||||
|  | index 8997518..f638342 100644
 | ||||||
|  | --- a/ltrace-elf.c
 | ||||||
|  | +++ b/ltrace-elf.c
 | ||||||
|  | @@ -859,7 +859,7 @@ populate_plt(struct process *proc, const char *filename,
 | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static void
 | ||||||
|  | +void
 | ||||||
|  |  delete_symbol_chain(struct library_symbol *libsym) | ||||||
|  |  { | ||||||
|  |  	while (libsym != NULL) { | ||||||
|  | diff --git a/ltrace-elf.h b/ltrace-elf.h
 | ||||||
|  | index db4ffe9..4a824c4 100644
 | ||||||
|  | --- a/ltrace-elf.h
 | ||||||
|  | +++ b/ltrace-elf.h
 | ||||||
|  | @@ -166,6 +166,7 @@ int elf_read_next_uleb128(Elf_Data *data, GElf_Xword *offset, uint64_t *retp);
 | ||||||
|  |  /* Return whether there's AMOUNT more bytes after OFFSET in DATA.  */ | ||||||
|  |  int elf_can_read_next(Elf_Data *data, GElf_Xword offset, GElf_Xword amount); | ||||||
|  |   | ||||||
|  | +void delete_symbol_chain(struct library_symbol *);
 | ||||||
|  |  #if __WORDSIZE == 32 | ||||||
|  |  #define PRI_ELF_ADDR		PRIx32 | ||||||
|  |  #define GELF_ADDR_CAST(x)	(void *)(uint32_t)(x) | ||||||
|  | diff --git a/sysdeps/linux-gnu/ppc/arch.h b/sysdeps/linux-gnu/ppc/arch.h
 | ||||||
|  | index bf9b5dc..7918a13 100644
 | ||||||
|  | --- a/sysdeps/linux-gnu/ppc/arch.h
 | ||||||
|  | +++ b/sysdeps/linux-gnu/ppc/arch.h
 | ||||||
|  | @@ -23,8 +23,8 @@
 | ||||||
|  |  #define LTRACE_PPC_ARCH_H | ||||||
|  |   | ||||||
|  |  #include <gelf.h> | ||||||
|  | +#include <stdbool.h>
 | ||||||
|  |   | ||||||
|  | -#define BREAKPOINT_VALUE { 0x7f, 0xe0, 0x00, 0x08 }
 | ||||||
|  |  #define BREAKPOINT_LENGTH 4 | ||||||
|  |  #define DECR_PC_AFTER_BREAK 0 | ||||||
|  |   | ||||||
|  | @@ -34,8 +34,33 @@
 | ||||||
|  |  #ifdef __powerpc64__ // Says 'ltrace' is 64 bits, says nothing about target. | ||||||
|  |  #define LT_ELFCLASS2	ELFCLASS64 | ||||||
|  |  #define LT_ELF_MACHINE2	EM_PPC64 | ||||||
|  | -#define ARCH_SUPPORTS_OPD
 | ||||||
|  | -#endif
 | ||||||
|  | +
 | ||||||
|  | +# ifdef __LITTLE_ENDIAN__
 | ||||||
|  | +# define BREAKPOINT_VALUE { 0x08, 0x00, 0xe0, 0x7f }
 | ||||||
|  | +# define ARCH_ENDIAN_LITTLE
 | ||||||
|  | +# else
 | ||||||
|  | +# define BREAKPOINT_VALUE { 0x7f, 0xe0, 0x00, 0x08 }
 | ||||||
|  | +# define ARCH_SUPPORTS_OPD
 | ||||||
|  | +# define ARCH_ENDIAN_BIG
 | ||||||
|  | +# endif
 | ||||||
|  | +
 | ||||||
|  | +# if _CALL_ELF != 2
 | ||||||
|  | +# define ARCH_SUPPORTS_OPD
 | ||||||
|  | +# define STACK_FRAME_OVERHEAD 112
 | ||||||
|  | +#  ifndef EF_PPC64_ABI
 | ||||||
|  | +#  define EF_PPC64_ABI 3
 | ||||||
|  | +#  endif
 | ||||||
|  | +# else /* _CALL_ELF == 2 ABIv2 */
 | ||||||
|  | +# define STACK_FRAME_OVERHEAD 32
 | ||||||
|  | +# endif /* CALL_ELF */
 | ||||||
|  | +
 | ||||||
|  | +#else
 | ||||||
|  | +#define BREAKPOINT_VALUE { 0x7f, 0xe0, 0x00, 0x08 }
 | ||||||
|  | +#define ARCH_ENDIAN_BIG
 | ||||||
|  | +# ifndef EF_PPC64_ABI
 | ||||||
|  | +# define EF_PPC64_ABI 3
 | ||||||
|  | +# endif
 | ||||||
|  | +#endif 	/* __powerpc64__ */
 | ||||||
|  |   | ||||||
|  |  #define ARCH_HAVE_SW_SINGLESTEP | ||||||
|  |  #define ARCH_HAVE_ADD_PLT_ENTRY | ||||||
|  | @@ -43,7 +68,6 @@
 | ||||||
|  |  #define ARCH_HAVE_TRANSLATE_ADDRESS | ||||||
|  |  #define ARCH_HAVE_DYNLINK_DONE | ||||||
|  |  #define ARCH_HAVE_FETCH_ARG | ||||||
|  | -#define ARCH_ENDIAN_BIG
 | ||||||
|  |  #define ARCH_HAVE_SIZEOF | ||||||
|  |  #define ARCH_HAVE_ALIGNOF | ||||||
|  |   | ||||||
|  | @@ -56,7 +80,8 @@ struct arch_ltelf_data {
 | ||||||
|  |  	Elf_Data *opd_data; | ||||||
|  |  	GElf_Addr opd_base; | ||||||
|  |  	GElf_Xword opd_size; | ||||||
|  | -	int secure_plt;
 | ||||||
|  | +	bool secure_plt : 1;
 | ||||||
|  | +	bool elfv2_abi  : 1;
 | ||||||
|  |   | ||||||
|  |  	Elf_Data *reladyn; | ||||||
|  |  	size_t reladyn_count; | ||||||
|  | diff --git a/sysdeps/linux-gnu/ppc/fetch.c b/sysdeps/linux-gnu/ppc/fetch.c
 | ||||||
|  | index ed38336..c9381c3 100644
 | ||||||
|  | --- a/sysdeps/linux-gnu/ppc/fetch.c
 | ||||||
|  | +++ b/sysdeps/linux-gnu/ppc/fetch.c
 | ||||||
|  | @@ -30,9 +30,11 @@
 | ||||||
|  |  #include "ptrace.h" | ||||||
|  |  #include "proc.h" | ||||||
|  |  #include "value.h" | ||||||
|  | +#include "ltrace-elf.h"
 | ||||||
|  |   | ||||||
|  |  static int allocate_gpr(struct fetch_context *ctx, struct process *proc, | ||||||
|  | -			struct arg_type_info *info, struct value *valuep);
 | ||||||
|  | +			struct arg_type_info *info, struct value *valuep,
 | ||||||
|  | +			size_t off, bool is_hfa_type);
 | ||||||
|  |   | ||||||
|  |  /* Floating point registers have the same width on 32-bit as well as | ||||||
|  |   * 64-bit PPC, but <ucontext.h> presents a different API depending on | ||||||
|  | @@ -62,7 +64,10 @@ struct fetch_context {
 | ||||||
|  |  		gregs64_t r64; | ||||||
|  |  	} regs; | ||||||
|  |  	struct fpregs_t fpregs; | ||||||
|  | -
 | ||||||
|  | +	int vgreg;
 | ||||||
|  | +	int struct_size;
 | ||||||
|  | +	int struct_hfa_size;
 | ||||||
|  | +	int struct_hfa_count;
 | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | @@ -74,7 +79,8 @@ fetch_context_init(struct process *proc, struct fetch_context *context)
 | ||||||
|  |  	if (proc->e_machine == EM_PPC) | ||||||
|  |  		context->stack_pointer = proc->stack_pointer + 8; | ||||||
|  |  	else | ||||||
|  | -		context->stack_pointer = proc->stack_pointer + 112;
 | ||||||
|  | +		context->stack_pointer = proc->stack_pointer
 | ||||||
|  | +			+ STACK_FRAME_OVERHEAD;
 | ||||||
|  |   | ||||||
|  |  	/* When ltrace is 64-bit, we might use PTRACE_GETREGS to | ||||||
|  |  	 * obtain 64-bit as well as 32-bit registers.  But if we do it | ||||||
|  | @@ -118,6 +124,11 @@ arch_fetch_arg_init(enum tof type, struct process *proc,
 | ||||||
|  |  		return NULL; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	context->vgreg = context->greg;
 | ||||||
|  | +	context->struct_size = 0;
 | ||||||
|  | +	context->struct_hfa_size = 0;
 | ||||||
|  | +	context->struct_hfa_count = 0;
 | ||||||
|  | +
 | ||||||
|  |  	/* Aggregates or unions of any length, and character strings | ||||||
|  |  	 * of length longer than 8 bytes, will be returned in a | ||||||
|  |  	 * storage buffer allocated by the caller. The caller will | ||||||
|  | @@ -125,8 +136,20 @@ arch_fetch_arg_init(enum tof type, struct process *proc,
 | ||||||
|  |  	 * in r3, causing the first explicit argument to be passed in | ||||||
|  |  	 * r4.  */ | ||||||
|  |  	context->ret_struct = ret_info->type == ARGTYPE_STRUCT; | ||||||
|  | -	if (context->ret_struct)
 | ||||||
|  | +	if (context->ret_struct) {
 | ||||||
|  | +#if _CALL_ELF == 2
 | ||||||
|  | +		/* if R3 points to stack, parameters will be in R4.  */
 | ||||||
|  | +		uint64_t pstack_end = ptrace(PTRACE_PEEKTEXT, proc->pid,
 | ||||||
|  | +					proc->stack_pointer, 0);
 | ||||||
|  | +		if (((arch_addr_t)context->regs.r64[3] > proc->stack_pointer)
 | ||||||
|  | +		    && (context->regs.r64[3] < pstack_end)) {
 | ||||||
|  | +			context->greg++;
 | ||||||
|  | +			context->stack_pointer += 8;
 | ||||||
|  | +		}
 | ||||||
|  | +#else
 | ||||||
|  |  		context->greg++; | ||||||
|  | +#endif
 | ||||||
|  | +	}
 | ||||||
|  |   | ||||||
|  |  	return context; | ||||||
|  |  } | ||||||
|  | @@ -144,7 +167,8 @@ arch_fetch_arg_clone(struct process *proc,
 | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  |  allocate_stack_slot(struct fetch_context *ctx, struct process *proc, | ||||||
|  | -		    struct arg_type_info *info, struct value *valuep)
 | ||||||
|  | +		    struct arg_type_info *info, struct value *valuep,
 | ||||||
|  | +		    bool is_hfa_type)
 | ||||||
|  |  { | ||||||
|  |  	size_t sz = type_sizeof(proc, info); | ||||||
|  |  	if (sz == (size_t)-1) | ||||||
|  | @@ -154,7 +178,14 @@ allocate_stack_slot(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |  	size_t off = 0; | ||||||
|  |  	if (proc->e_machine == EM_PPC && a < 4) | ||||||
|  |  		a = 4; | ||||||
|  | +#if _CALL_ELF == 2
 | ||||||
|  | +	else if (proc->e_machine == EM_PPC64 && sz == 4 && is_hfa_type)
 | ||||||
|  | +		a = 4;
 | ||||||
|  | +	else
 | ||||||
|  | +		a = 8;
 | ||||||
|  | +#else
 | ||||||
|  |  	else if (proc->e_machine == EM_PPC64 && a < 8) | ||||||
|  | +#endif
 | ||||||
|  |  		a = 8; | ||||||
|  |   | ||||||
|  |  	/* XXX Remove the two double casts when arch_addr_t | ||||||
|  | @@ -164,7 +195,7 @@ allocate_stack_slot(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |   | ||||||
|  |  	if (valuep != NULL) | ||||||
|  |  		value_in_inferior(valuep, ctx->stack_pointer + off); | ||||||
|  | -	ctx->stack_pointer += sz;
 | ||||||
|  | +	ctx->stack_pointer += a;
 | ||||||
|  |   | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  | @@ -216,19 +247,34 @@ align_small_int(unsigned char *buf, size_t w, size_t sz)
 | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  |  allocate_gpr(struct fetch_context *ctx, struct process *proc, | ||||||
|  | -	     struct arg_type_info *info, struct value *valuep)
 | ||||||
|  | +	     struct arg_type_info *info, struct value *valuep,
 | ||||||
|  | +	     size_t off, bool is_hfa_type)
 | ||||||
|  |  { | ||||||
|  |  	if (ctx->greg > 10) | ||||||
|  | -		return allocate_stack_slot(ctx, proc, info, valuep);
 | ||||||
|  | +		return allocate_stack_slot(ctx, proc, info, valuep, is_hfa_type);
 | ||||||
|  |   | ||||||
|  | -	int reg_num = ctx->greg++;
 | ||||||
|  | -	if (valuep == NULL)
 | ||||||
|  | -		return 0;
 | ||||||
|  | +	int reg_num = ctx->greg;
 | ||||||
|  |   | ||||||
|  |  	size_t sz = type_sizeof(proc, info); | ||||||
|  |  	if (sz == (size_t)-1) | ||||||
|  |  		return -1; | ||||||
|  |  	assert(sz == 1 || sz == 2 || sz == 4 || sz == 8); | ||||||
|  | +#if _CALL_ELF == 2
 | ||||||
|  | +	/* Consume the stack slot corresponding to this arg.  */
 | ||||||
|  | +	if ((sz + off) >= 8)
 | ||||||
|  | +		ctx->greg++;
 | ||||||
|  | +
 | ||||||
|  | +	if (is_hfa_type)
 | ||||||
|  | +		ctx->stack_pointer += sz;
 | ||||||
|  | +	else
 | ||||||
|  | +		ctx->stack_pointer += 8;
 | ||||||
|  | +#else
 | ||||||
|  | +	ctx->greg++;
 | ||||||
|  | +#endif
 | ||||||
|  | +
 | ||||||
|  | +	if (valuep == NULL)
 | ||||||
|  | +		return 0;
 | ||||||
|  | +
 | ||||||
|  |  	if (value_reserve(valuep, sz) == NULL) | ||||||
|  |  		return -1; | ||||||
|  |   | ||||||
|  | @@ -240,13 +286,14 @@ allocate_gpr(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |  	u.i64 = read_gpr(ctx, proc, reg_num); | ||||||
|  |  	if (proc->e_machine == EM_PPC) | ||||||
|  |  		align_small_int(u.buf, 8, sz); | ||||||
|  | -	memcpy(value_get_raw_data(valuep), u.buf, sz);
 | ||||||
|  | +	memcpy(value_get_raw_data(valuep), u.buf + off, sz);
 | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  |  allocate_float(struct fetch_context *ctx, struct process *proc, | ||||||
|  | -	       struct arg_type_info *info, struct value *valuep)
 | ||||||
|  | +	       struct arg_type_info *info, struct value *valuep,
 | ||||||
|  | +	       size_t off, bool is_hfa_type)
 | ||||||
|  |  { | ||||||
|  |  	int pool = proc->e_machine == EM_PPC64 ? 13 : 8; | ||||||
|  |  	if (ctx->freg <= pool) { | ||||||
|  | @@ -257,8 +304,12 @@ allocate_float(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |  		} u = { .d = ctx->fpregs.fpregs[ctx->freg] }; | ||||||
|  |   | ||||||
|  |  		ctx->freg++; | ||||||
|  | +
 | ||||||
|  | +		if (!is_hfa_type)
 | ||||||
|  | +			ctx->vgreg++;
 | ||||||
|  | +
 | ||||||
|  |  		if (proc->e_machine == EM_PPC64) | ||||||
|  | -			allocate_gpr(ctx, proc, info, NULL);
 | ||||||
|  | +			allocate_gpr(ctx, proc, info, NULL, off, is_hfa_type);
 | ||||||
|  |   | ||||||
|  |  		size_t sz = sizeof(double); | ||||||
|  |  		if (info->type == ARGTYPE_FLOAT) { | ||||||
|  | @@ -272,8 +323,128 @@ allocate_float(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |  		memcpy(value_get_raw_data(valuep), u.buf, sz); | ||||||
|  |  		return 0; | ||||||
|  |  	} | ||||||
|  | -	return allocate_stack_slot(ctx, proc, info, valuep);
 | ||||||
|  | +	return allocate_stack_slot(ctx, proc, info, valuep, is_hfa_type);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +#if _CALL_ELF == 2
 | ||||||
|  | +static int
 | ||||||
|  | +allocate_hfa(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  | +	     struct arg_type_info *info, struct value *valuep,
 | ||||||
|  | +	     enum arg_type hfa_type, size_t hfa_count)
 | ||||||
|  | +{
 | ||||||
|  | +	size_t sz = type_sizeof(proc, info);
 | ||||||
|  | +	if (sz == (size_t)-1)
 | ||||||
|  | +		return -1;
 | ||||||
|  | +
 | ||||||
|  | +	ctx->struct_hfa_size += sz;
 | ||||||
|  | +
 | ||||||
|  | +	/* There are two changes regarding structure return types:
 | ||||||
|  | +	 * * heterogeneous float/vector structs are returned
 | ||||||
|  | +	 *   in (multiple) FP/vector registers,
 | ||||||
|  | +	 *   instead of via implicit reference.
 | ||||||
|  | +	 * * small structs (up to 16 bytes) are return
 | ||||||
|  | +	 *   in one or two GPRs, instead of via implicit reference.
 | ||||||
|  | +	 *
 | ||||||
|  | +	 * Other structures (larger than 16 bytes, not heterogeneous)
 | ||||||
|  | +	 * are still returned via implicit reference (i.e. a pointer
 | ||||||
|  | +	 * to memory where to return the struct being passed in r3).
 | ||||||
|  | +	 * Of course, whether or not an implicit reference pointer
 | ||||||
|  | +	 * is present will shift the remaining arguments,
 | ||||||
|  | +	 * so you need to get this right for ELFv2 in order
 | ||||||
|  | +	 * to get the arguments correct.
 | ||||||
|  | +	 * If an actual parameter is known to correspond to an HFA
 | ||||||
|  | +	 * formal parameter, each element is passed in the next
 | ||||||
|  | +	 * available floating-point argument register starting at fp1
 | ||||||
|  | +	 * until the fp13. The remaining elements of the aggregate are
 | ||||||
|  | +	 * passed on the stack.  */
 | ||||||
|  | +	size_t slot_off = 0;
 | ||||||
|  | +
 | ||||||
|  | +	unsigned char *buf = value_reserve(valuep, sz);
 | ||||||
|  | +	if (buf == NULL)
 | ||||||
|  | +		return -1;
 | ||||||
|  | +
 | ||||||
|  | +	struct arg_type_info *hfa_info = type_get_simple(hfa_type);
 | ||||||
|  | +	size_t hfa_sz = type_sizeof(proc, hfa_info);
 | ||||||
|  | +
 | ||||||
|  | +	if (hfa_count > 8)
 | ||||||
|  | +		ctx->struct_hfa_count += hfa_count;
 | ||||||
|  | +
 | ||||||
|  | +	while (hfa_count > 0 && ctx->freg <= 13) {
 | ||||||
|  | +		int rc;
 | ||||||
|  | +		struct value tmp;
 | ||||||
|  | +
 | ||||||
|  | +		value_init(&tmp, proc, NULL, hfa_info, 0);
 | ||||||
|  | +
 | ||||||
|  | +		/* Hetereogeneous struct - get value on GPR or stack.  */
 | ||||||
|  | +		if (((hfa_type == ARGTYPE_FLOAT
 | ||||||
|  | +		    || hfa_type == ARGTYPE_DOUBLE)
 | ||||||
|  | +		      && hfa_count <= 8))
 | ||||||
|  | +			rc = allocate_float(ctx, proc, hfa_info, &tmp,
 | ||||||
|  | +						slot_off, true);
 | ||||||
|  | +		else
 | ||||||
|  | +			rc = allocate_gpr(ctx, proc, hfa_info, &tmp,
 | ||||||
|  | +						slot_off, true);
 | ||||||
|  | +
 | ||||||
|  | +		memcpy(buf, value_get_data(&tmp, NULL), hfa_sz);
 | ||||||
|  | +
 | ||||||
|  | +		slot_off += hfa_sz;
 | ||||||
|  | +		buf += hfa_sz;
 | ||||||
|  | +		hfa_count--;
 | ||||||
|  | +		if (slot_off == 8) {
 | ||||||
|  | +			slot_off = 0;
 | ||||||
|  | +			ctx->vgreg++;
 | ||||||
|  | +		}
 | ||||||
|  | +
 | ||||||
|  | +		value_destroy(&tmp);
 | ||||||
|  | +		if (rc < 0)
 | ||||||
|  | +			return -1;
 | ||||||
|  | +	}
 | ||||||
|  | +	if (hfa_count == 0)
 | ||||||
|  | +		return 0;
 | ||||||
|  | +
 | ||||||
|  | +	/* if no remaining FP, GPR corresponding to slot is used
 | ||||||
|  | +	* Mostly it is in part of r10.  */
 | ||||||
|  | +	if (ctx->struct_hfa_size <= 64 && ctx->vgreg == 10) {
 | ||||||
|  | +		while (ctx->vgreg <= 10) {
 | ||||||
|  | +			struct value tmp;
 | ||||||
|  | +			value_init(&tmp, proc, NULL, hfa_info, 0);
 | ||||||
|  | +			union {
 | ||||||
|  | +				uint64_t i64;
 | ||||||
|  | +				unsigned char buf[0];
 | ||||||
|  | +			} u;
 | ||||||
|  | +
 | ||||||
|  | +			u.i64 = read_gpr(ctx, proc, ctx->vgreg);
 | ||||||
|  | +
 | ||||||
|  | +			memcpy(buf, u.buf + slot_off, hfa_sz);
 | ||||||
|  | +			slot_off += hfa_sz;
 | ||||||
|  | +			buf += hfa_sz;
 | ||||||
|  | +			hfa_count--;
 | ||||||
|  | +			ctx->stack_pointer += hfa_sz;
 | ||||||
|  | +			if (slot_off >= 8 ) {
 | ||||||
|  | +				slot_off = 0;
 | ||||||
|  | +				ctx->vgreg++;
 | ||||||
|  | +			}
 | ||||||
|  | +			value_destroy(&tmp);
 | ||||||
|  | +		}
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  | +	if (hfa_count == 0)
 | ||||||
|  | +		return 0;
 | ||||||
|  | +
 | ||||||
|  | +	/* Remaining values are on stack */
 | ||||||
|  | +	while (hfa_count) {
 | ||||||
|  | +		struct value tmp;
 | ||||||
|  | +		value_init(&tmp, proc, NULL, hfa_info, 0);
 | ||||||
|  | +
 | ||||||
|  | +		value_in_inferior(&tmp, ctx->stack_pointer);
 | ||||||
|  | +		memcpy(buf, value_get_data(&tmp, NULL), hfa_sz);
 | ||||||
|  | +		ctx->stack_pointer += hfa_sz;
 | ||||||
|  | +		buf += hfa_sz;
 | ||||||
|  | +		hfa_count--;
 | ||||||
|  | +	}
 | ||||||
|  | +	return 0;
 | ||||||
|  |  } | ||||||
|  | +#endif
 | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  |  allocate_argument(struct fetch_context *ctx, struct process *proc, | ||||||
|  | @@ -287,13 +458,25 @@ allocate_argument(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |   | ||||||
|  |  	case ARGTYPE_FLOAT: | ||||||
|  |  	case ARGTYPE_DOUBLE: | ||||||
|  | -		return allocate_float(ctx, proc, info, valuep);
 | ||||||
|  | +		return allocate_float(ctx, proc, info, valuep,
 | ||||||
|  | +					8 - type_sizeof(proc,info), false);
 | ||||||
|  |   | ||||||
|  |  	case ARGTYPE_STRUCT: | ||||||
|  |  		if (proc->e_machine == EM_PPC) { | ||||||
|  |  			if (value_pass_by_reference(valuep) < 0) | ||||||
|  |  				return -1; | ||||||
|  |  		} else { | ||||||
|  | +#if _CALL_ELF == 2
 | ||||||
|  | +			struct arg_type_info *hfa_info;
 | ||||||
|  | +			size_t hfa_size;
 | ||||||
|  | +			hfa_info = type_get_hfa_type(info, &hfa_size);
 | ||||||
|  | +			if (hfa_info != NULL ) {
 | ||||||
|  | +				size_t sz = type_sizeof(proc, info);
 | ||||||
|  | +				ctx->struct_size += sz;
 | ||||||
|  | +				return allocate_hfa(ctx, proc, info, valuep,
 | ||||||
|  | +						hfa_info->type, hfa_size);
 | ||||||
|  | +			}
 | ||||||
|  | +#endif
 | ||||||
|  |  			/* PPC64: Fixed size aggregates and unions passed by | ||||||
|  |  			 * value are mapped to as many doublewords of the | ||||||
|  |  			 * parameter save area as the value uses in memory. | ||||||
|  | @@ -326,6 +509,10 @@ allocate_argument(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |  	size_t sz = type_sizeof(proc, valuep->type); | ||||||
|  |  	if (sz == (size_t)-1) | ||||||
|  |  		return -1; | ||||||
|  | +
 | ||||||
|  | +	if (ctx->ret_struct)
 | ||||||
|  | +		ctx->struct_size += sz;
 | ||||||
|  | +
 | ||||||
|  |  	size_t slots = (sz + width - 1) / width;  /* Round up.  */ | ||||||
|  |  	unsigned char *buf = value_reserve(valuep, slots * width); | ||||||
|  |  	if (buf == NULL) | ||||||
|  | @@ -346,9 +533,11 @@ allocate_argument(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |  		struct arg_type_info *fp_info | ||||||
|  |  			= type_get_fp_equivalent(valuep->type); | ||||||
|  |  		if (fp_info != NULL) | ||||||
|  | -			rc = allocate_float(ctx, proc, fp_info, &val);
 | ||||||
|  | +			rc = allocate_float(ctx, proc, fp_info, &val,
 | ||||||
|  | +					8-type_sizeof(proc,info), false);
 | ||||||
|  |  		else | ||||||
|  | -			rc = allocate_gpr(ctx, proc, long_info, &val);
 | ||||||
|  | +			rc = allocate_gpr(ctx, proc, long_info, &val,
 | ||||||
|  | +					0, false);
 | ||||||
|  |   | ||||||
|  |  		if (rc >= 0) { | ||||||
|  |  			memcpy(ptr, value_get_data(&val, NULL), width); | ||||||
|  | @@ -363,6 +552,7 @@ allocate_argument(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |  			return rc; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +#ifndef __LITTLE_ENDIAN__
 | ||||||
|  |  	/* Small values need post-processing.  */ | ||||||
|  |  	if (sz < width) { | ||||||
|  |  		switch (info->type) { | ||||||
|  | @@ -394,6 +584,7 @@ allocate_argument(struct fetch_context *ctx, struct process *proc,
 | ||||||
|  |  			break; | ||||||
|  |  		} | ||||||
|  |  	} | ||||||
|  | +#endif
 | ||||||
|  |   | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  | @@ -411,7 +602,22 @@ arch_fetch_retval(struct fetch_context *ctx, enum tof type,
 | ||||||
|  |  		  struct process *proc, struct arg_type_info *info, | ||||||
|  |  		  struct value *valuep) | ||||||
|  |  { | ||||||
|  | +	if (fetch_context_init(proc, ctx) < 0)
 | ||||||
|  | +		return -1;
 | ||||||
|  | +
 | ||||||
|  | +#if _CALL_ELF == 2
 | ||||||
|  | +	void *ptr = (void *)(ctx->regs.r64[1]+32);
 | ||||||
|  | +	uint64_t val = ptrace(PTRACE_PEEKTEXT, proc->pid, ptr, 0);
 | ||||||
|  | +
 | ||||||
|  | +	if (ctx->ret_struct
 | ||||||
|  | +	   && ((ctx->struct_size > 64
 | ||||||
|  | +	      || ctx->struct_hfa_count > 8
 | ||||||
|  | +	      || (ctx->struct_hfa_size == 0 && ctx->struct_size > 56)
 | ||||||
|  | +	      || (ctx->regs.r64[3] == ctx->regs.r64[1]+32)
 | ||||||
|  | +	      || (ctx->regs.r64[3] == val )))) {
 | ||||||
|  | +#else
 | ||||||
|  |  	if (ctx->ret_struct) { | ||||||
|  | +#endif
 | ||||||
|  |  		assert(info->type == ARGTYPE_STRUCT); | ||||||
|  |   | ||||||
|  |  		uint64_t addr = read_gpr(ctx, proc, 3); | ||||||
|  | @@ -424,8 +630,6 @@ arch_fetch_retval(struct fetch_context *ctx, enum tof type,
 | ||||||
|  |  		return 0; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	if (fetch_context_init(proc, ctx) < 0)
 | ||||||
|  | -		return -1;
 | ||||||
|  |  	return allocate_argument(ctx, proc, info, valuep); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | diff --git a/sysdeps/linux-gnu/ppc/plt.c b/sysdeps/linux-gnu/ppc/plt.c
 | ||||||
|  | index 332daa8..45ed7fb 100644
 | ||||||
|  | --- a/sysdeps/linux-gnu/ppc/plt.c
 | ||||||
|  | +++ b/sysdeps/linux-gnu/ppc/plt.c
 | ||||||
|  | @@ -136,7 +136,11 @@
 | ||||||
|  |   */ | ||||||
|  |   | ||||||
|  |  #define PPC_PLT_STUB_SIZE 16 | ||||||
|  | -#define PPC64_PLT_STUB_SIZE 8 //xxx
 | ||||||
|  | +#if _CALL_ELF != 2
 | ||||||
|  | +#define PPC64_PLT_STUB_SIZE 8
 | ||||||
|  | +#else
 | ||||||
|  | +#define PPC64_PLT_STUB_SIZE 4
 | ||||||
|  | +#endif
 | ||||||
|  |   | ||||||
|  |  static inline int | ||||||
|  |  host_powerpc64() | ||||||
|  | @@ -186,8 +190,13 @@ ppc32_delayed_symbol(struct library_symbol *libsym)
 | ||||||
|  |  	if ((insn1 & BRANCH_MASK) == B_INSN | ||||||
|  |  	    || ((insn2 & BRANCH_MASK) == B_INSN | ||||||
|  |  		/* XXX double cast  */ | ||||||
|  | +#ifdef __LITTLE_ENDIAN__
 | ||||||
|  | +		&& (ppc_branch_dest(libsym->enter_addr + 4, insn1)
 | ||||||
|  | +		    == (arch_addr_t) (long) libsym->lib->arch.pltgot_addr)))
 | ||||||
|  | +#else
 | ||||||
|  |  		&& (ppc_branch_dest(libsym->enter_addr + 4, insn2) | ||||||
|  |  		    == (arch_addr_t) (long) libsym->lib->arch.pltgot_addr))) | ||||||
|  | +#endif
 | ||||||
|  |  	{ | ||||||
|  |  		mark_as_resolved(libsym, libsym->arch.resolved_value); | ||||||
|  |  	} | ||||||
|  | @@ -206,7 +215,7 @@ arch_dynlink_done(struct process *proc)
 | ||||||
|  |  				"couldn't read PLT value for %s(%p): %s\n", | ||||||
|  |  				libsym->name, libsym->enter_addr, | ||||||
|  |  				strerror(errno)); | ||||||
|  | -			return;
 | ||||||
|  | +				return;
 | ||||||
|  |  		} | ||||||
|  |   | ||||||
|  |  		if (proc->e_machine == EM_PPC) | ||||||
|  | @@ -227,8 +236,14 @@ reloc_is_irelative(int machine, GElf_Rela *rela)
 | ||||||
|  |  { | ||||||
|  |  	bool irelative = false; | ||||||
|  |  	if (machine == EM_PPC64) { | ||||||
|  | -#ifdef R_PPC64_JMP_IREL
 | ||||||
|  | +#ifdef __LITTLE_ENDIAN__
 | ||||||
|  | +# ifdef R_PPC64_IRELATIVE
 | ||||||
|  | +		irelative = GELF_R_TYPE(rela->r_info) == R_PPC64_IRELATIVE;
 | ||||||
|  | +# endif
 | ||||||
|  | +#else
 | ||||||
|  | +# ifdef R_PPC64_JMP_IREL
 | ||||||
|  |  		irelative = GELF_R_TYPE(rela->r_info) == R_PPC64_JMP_IREL; | ||||||
|  | +# endif
 | ||||||
|  |  #endif | ||||||
|  |  	} else { | ||||||
|  |  		assert(machine == EM_PPC); | ||||||
|  | @@ -285,6 +300,7 @@ arch_translate_address_dyn(struct process *proc,
 | ||||||
|  |  			   arch_addr_t addr, arch_addr_t *ret) | ||||||
|  |  { | ||||||
|  |  	if (proc->e_machine == EM_PPC64) { | ||||||
|  | +#if _CALL_ELF != 2
 | ||||||
|  |  		uint64_t value; | ||||||
|  |  		if (proc_read_64(proc, addr, &value) < 0) { | ||||||
|  |  			fprintf(stderr, | ||||||
|  | @@ -296,6 +312,7 @@ arch_translate_address_dyn(struct process *proc,
 | ||||||
|  |  		 * arch_addr_t becomes integral type.  */ | ||||||
|  |  		*ret = (arch_addr_t)(uintptr_t)value; | ||||||
|  |  		return 0; | ||||||
|  | +#endif
 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	*ret = addr; | ||||||
|  | @@ -306,7 +323,8 @@ int
 | ||||||
|  |  arch_translate_address(struct ltelf *lte, | ||||||
|  |  		       arch_addr_t addr, arch_addr_t *ret) | ||||||
|  |  { | ||||||
|  | -	if (lte->ehdr.e_machine == EM_PPC64) {
 | ||||||
|  | +	if (lte->ehdr.e_machine == EM_PPC64
 | ||||||
|  | +	    && !lte->arch.elfv2_abi) {
 | ||||||
|  |  		/* XXX The double cast should be removed when | ||||||
|  |  		 * arch_addr_t becomes integral type.  */ | ||||||
|  |  		GElf_Xword offset | ||||||
|  | @@ -430,7 +448,16 @@ reloc_copy_if_irelative(GElf_Rela *rela, void *data)
 | ||||||
|  |  int | ||||||
|  |  arch_elf_init(struct ltelf *lte, struct library *lib) | ||||||
|  |  { | ||||||
|  | +
 | ||||||
|  | +	/* Check for ABIv2 in ELF header processor specific flag.  */
 | ||||||
|  | +#ifndef EF_PPC64_ABI
 | ||||||
|  | +	assert (! (lte->ehdr.e_flags & 3 ) == 2)
 | ||||||
|  | +#else
 | ||||||
|  | +	lte->arch.elfv2_abi=((lte->ehdr.e_flags & EF_PPC64_ABI) == 2) ;
 | ||||||
|  | +#endif
 | ||||||
|  | +
 | ||||||
|  |  	if (lte->ehdr.e_machine == EM_PPC64 | ||||||
|  | +	    && !lte->arch.elfv2_abi
 | ||||||
|  |  	    && load_opd_data(lte, lib) < 0) | ||||||
|  |  		return -1; | ||||||
|  |   | ||||||
|  | @@ -599,7 +626,7 @@ read_plt_slot_value(struct process *proc, GElf_Addr addr, GElf_Addr *valp)
 | ||||||
|  |  	uint64_t l; | ||||||
|  |  	/* XXX double cast.  */ | ||||||
|  |  	if (proc_read_64(proc, (arch_addr_t)(uintptr_t)addr, &l) < 0) { | ||||||
|  | -		fprintf(stderr, "ptrace .plt slot value @%#" PRIx64": %s\n",
 | ||||||
|  | +		debug(DEBUG_EVENT, "ptrace .plt slot value @%#" PRIx64": %s",
 | ||||||
|  |  			addr, strerror(errno)); | ||||||
|  |  		return -1; | ||||||
|  |  	} | ||||||
|  | @@ -616,7 +643,7 @@ unresolve_plt_slot(struct process *proc, GElf_Addr addr, GElf_Addr value)
 | ||||||
|  |  	 * pointers intact.  Hence the only adjustment that we need to | ||||||
|  |  	 * do is to IP.  */ | ||||||
|  |  	if (ptrace(PTRACE_POKETEXT, proc->pid, addr, value) < 0) { | ||||||
|  | -		fprintf(stderr, "failed to unresolve .plt slot: %s\n",
 | ||||||
|  | +		debug(DEBUG_EVENT, "failed to unresolve .plt slot: %s",
 | ||||||
|  |  			strerror(errno)); | ||||||
|  |  		return -1; | ||||||
|  |  	} | ||||||
|  | @@ -629,9 +656,48 @@ arch_elf_add_func_entry(struct process *proc, struct ltelf *lte,
 | ||||||
|  |  			arch_addr_t addr, const char *name, | ||||||
|  |  			struct library_symbol **ret) | ||||||
|  |  { | ||||||
|  | -	if (lte->ehdr.e_machine != EM_PPC || lte->ehdr.e_type == ET_DYN)
 | ||||||
|  | +#ifndef PPC64_LOCAL_ENTRY_OFFSET
 | ||||||
|  | +	assert(! lte->arch.elfv2_abi);
 | ||||||
|  | +#else
 | ||||||
|  | +	/* With ABIv2 st_other field contains an offset.  */
 | ||||||
|  | +	 if (lte->arch.elfv2_abi)
 | ||||||
|  | +		addr += PPC64_LOCAL_ENTRY_OFFSET(sym->st_other);
 | ||||||
|  | +#endif
 | ||||||
|  | +
 | ||||||
|  | +	int st_info = GELF_ST_TYPE(sym->st_info);
 | ||||||
|  | +
 | ||||||
|  | +	if ((lte->ehdr.e_machine != EM_PPC && sym->st_other == 0)
 | ||||||
|  | +	    || lte->ehdr.e_type == ET_DYN
 | ||||||
|  | +	    || (st_info == STT_FUNC && ! sym->st_other))
 | ||||||
|  |  		return PLT_DEFAULT; | ||||||
|  |   | ||||||
|  | +	if (st_info == STT_FUNC) {
 | ||||||
|  | +		/* Put the default symbol to the chain.
 | ||||||
|  | +		 * The addr has already been updated with
 | ||||||
|  | +		 * symbol offset  */
 | ||||||
|  | +		char *full_name = strdup(name);
 | ||||||
|  | +		if (full_name == NULL) {
 | ||||||
|  | +			fprintf(stderr, "couldn't copy name of %s: %s\n",
 | ||||||
|  | +			name, strerror(errno));
 | ||||||
|  | +			free(full_name);
 | ||||||
|  | +			return PLT_FAIL;
 | ||||||
|  | +		}
 | ||||||
|  | +		struct library_symbol *libsym = malloc(sizeof *libsym);
 | ||||||
|  | +		if (libsym == NULL
 | ||||||
|  | +		    || library_symbol_init(libsym, addr, full_name, 1,
 | ||||||
|  | +					   LS_TOPLT_NONE) < 0) {
 | ||||||
|  | +			free(libsym);
 | ||||||
|  | +			delete_symbol_chain(libsym);
 | ||||||
|  | +			libsym = NULL;
 | ||||||
|  | +			fprintf(stderr, "Couldn't add symbol %s"
 | ||||||
|  | +				"for tracing.\n", name);
 | ||||||
|  | +		}
 | ||||||
|  | +		full_name = NULL;
 | ||||||
|  | +		libsym->next = *ret;
 | ||||||
|  | +		*ret = libsym;
 | ||||||
|  | +		return PLT_OK;
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  |  	bool ifunc = false; | ||||||
|  |  #ifdef STT_GNU_IFUNC | ||||||
|  |  	ifunc = GELF_ST_TYPE(sym->st_info) == STT_GNU_IFUNC; | ||||||
|  | @@ -761,9 +827,15 @@ arch_elf_add_plt_entry(struct process *proc, struct ltelf *lte,
 | ||||||
|  |  	assert(plt_slot_addr >= lte->plt_addr | ||||||
|  |  	       || plt_slot_addr < lte->plt_addr + lte->plt_size); | ||||||
|  |   | ||||||
|  | +	/* Should avoid to do read if dynamic linker hasn't run yet
 | ||||||
|  | +	 * or allow -1 a valid return code.  */
 | ||||||
|  |  	GElf_Addr plt_slot_value; | ||||||
|  | -	if (read_plt_slot_value(proc, plt_slot_addr, &plt_slot_value) < 0)
 | ||||||
|  | -		goto fail;
 | ||||||
|  | +	if (read_plt_slot_value(proc, plt_slot_addr, &plt_slot_value) < 0) {
 | ||||||
|  | +		if (!lte->arch.elfv2_abi)
 | ||||||
|  | +			goto fail;
 | ||||||
|  | +		else
 | ||||||
|  | +			return PPC_PLT_UNRESOLVED;
 | ||||||
|  | +	}
 | ||||||
|  |   | ||||||
|  |  	struct library_symbol *libsym = malloc(sizeof(*libsym)); | ||||||
|  |  	if (libsym == NULL) { | ||||||
|  | @@ -997,8 +1069,12 @@ ppc_plt_bp_continue(struct breakpoint *bp, struct process *proc)
 | ||||||
|  |  			return; | ||||||
|  |  		} | ||||||
|  |   | ||||||
|  | +#if _CALL_ELF == 2
 | ||||||
|  | +		continue_after_breakpoint(proc, bp);
 | ||||||
|  | +#else
 | ||||||
|  |  		jump_to_entry_point(proc, bp); | ||||||
|  |  		continue_process(proc->pid); | ||||||
|  | +#endif
 | ||||||
|  |  		return; | ||||||
|  |   | ||||||
|  |  	case PPC64_PLT_STUB: | ||||||
|  | @@ -1123,7 +1199,11 @@ arch_library_symbol_init(struct library_symbol *libsym)
 | ||||||
|  |  	/* We set type explicitly in the code above, where we have the | ||||||
|  |  	 * necessary context.  This is for calls from ltrace-elf.c and | ||||||
|  |  	 * such.  */ | ||||||
|  | +#if _CALL_ELF == 2
 | ||||||
|  | +	libsym->arch.type = PPC_PLT_UNRESOLVED;
 | ||||||
|  | +#else
 | ||||||
|  |  	libsym->arch.type = PPC_DEFAULT; | ||||||
|  | +#endif
 | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | diff --git a/sysdeps/linux-gnu/ppc/trace.c b/sysdeps/linux-gnu/ppc/trace.c
 | ||||||
|  | index ee9a6b5..5aab538 100644
 | ||||||
|  | --- a/sysdeps/linux-gnu/ppc/trace.c
 | ||||||
|  | +++ b/sysdeps/linux-gnu/ppc/trace.c
 | ||||||
|  | @@ -65,9 +65,15 @@ syscall_p(struct process *proc, int status, int *sysnum)
 | ||||||
|  |  	if (WIFSTOPPED(status) | ||||||
|  |  	    && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { | ||||||
|  |  		long pc = (long)get_instruction_pointer(proc); | ||||||
|  | +#ifndef __LITTLE_ENDIAN__
 | ||||||
|  |  		int insn = | ||||||
|  |  		    (int)ptrace(PTRACE_PEEKTEXT, proc->pid, pc - sizeof(long), | ||||||
|  |  				0); | ||||||
|  | +#else
 | ||||||
|  | +		int insn =
 | ||||||
|  | +		    (int)ptrace(PTRACE_PEEKTEXT, proc->pid, pc - sizeof(int),
 | ||||||
|  | +				0);
 | ||||||
|  | +#endif
 | ||||||
|  |   | ||||||
|  |  		if (insn == SYSCALL_INSN) { | ||||||
|  |  			*sysnum = | ||||||
|  | diff -up ltrace-0.7.91/sysdeps/linux-gnu/ppc/trace.c\~ ltrace-0.7.91/sysdeps/linux-gnu/ppc/trace.c
 | ||||||
|  | --- ltrace-0.7.91/sysdeps/linux-gnu/ppc/trace.c~	2014-08-08 14:05:58.000000000 +0200
 | ||||||
|  | +++ ltrace-0.7.91/sysdeps/linux-gnu/ppc/trace.c	2014-08-08 14:07:55.000000000 +0200
 | ||||||
|  | @@ -133,7 +133,11 @@ arch_sw_singlestep(struct process *proc,
 | ||||||
|  |  			return SWS_FAIL; | ||||||
|  |  		uint32_t insn; | ||||||
|  |  #ifdef __powerpc64__ | ||||||
|  | +# ifdef __LITTLE_ENDIAN__
 | ||||||
|  | +		insn = (uint32_t) l;
 | ||||||
|  | +# else
 | ||||||
|  |  		insn = l >> 32; | ||||||
|  | +# endif
 | ||||||
|  |  #else | ||||||
|  |  		insn = l; | ||||||
|  |  #endif | ||||||
|  | diff -up ltrace-0.7.91/configure\~ ltrace-0.7.91/configure
 | ||||||
|  | --- ltrace-0.7.91/configure~	2014-08-08 14:09:12.000000000 +0200
 | ||||||
|  | +++ ltrace-0.7.91/configure	2014-08-08 14:18:30.000000000 +0200
 | ||||||
|  | @@ -2555,7 +2555,7 @@ case "${host_cpu}" in
 | ||||||
|  |      arm*|sa110)		HOST_CPU="arm" ;; | ||||||
|  |      cris*)		HOST_CPU="cris" ;; | ||||||
|  |      mips*)		HOST_CPU="mips" ;; | ||||||
|  | -    powerpc|powerpc64)	HOST_CPU="ppc" ;;
 | ||||||
|  | +    powerpc|powerpc64|powerpc64le)	HOST_CPU="ppc" ;;
 | ||||||
|  |      sun4u|sparc64)	HOST_CPU="sparc" ;; | ||||||
|  |      s390x)		HOST_CPU="s390" ;; | ||||||
|  |      i?86|x86_64)	HOST_CPU="x86" ;; | ||||||
|  | @@ -12094,7 +12094,7 @@ if test x"$enable_libunwind" = xyes; the
 | ||||||
|  |        arm*|sa110)         UNWIND_ARCH="arm" ;; | ||||||
|  |        i?86)               UNWIND_ARCH="x86" ;; | ||||||
|  |        powerpc)            UNWIND_ARCH="ppc32" ;; | ||||||
|  | -      powerpc64)          UNWIND_ARCH="ppc64" ;;
 | ||||||
|  | +      powerpc64|powerpc64le)          UNWIND_ARCH="ppc64" ;;
 | ||||||
|  |        mips*)              UNWIND_ARCH="mips" ;; | ||||||
|  |        *)                  UNWIND_ARCH="${host_cpu}" ;; | ||||||
|  |    esac | ||||||
							
								
								
									
										69
									
								
								SOURCES/ltrace-0.7.91-s390-fetch-syscall.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								SOURCES/ltrace-0.7.91-s390-fetch-syscall.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,69 @@ | |||||||
|  | @@ -, +, @@ 
 | ||||||
|  |    exe->mount("source", "target", "filesystemtype", 0, nil <unfinished ...> | ||||||
|  |    mount@SYS("", "target", "filesystemtype", 0, nil)                 = -2 | ||||||
|  |    <... mount resumed>                                               = -1 | ||||||
|  | ---
 | ||||||
|  |  sysdeps/linux-gnu/s390/fetch.c |   17 ++++++++++++----- | ||||||
|  |  1 files changed, 12 insertions(+), 5 deletions(-) | ||||||
|  | --- a/sysdeps/linux-gnu/s390/fetch.c	
 | ||||||
|  | +++ a/sysdeps/linux-gnu/s390/fetch.c	
 | ||||||
|  | @@ -23,6 +23,7 @@ 
 | ||||||
|  |  #include <sys/ucontext.h> | ||||||
|  |  #include <assert.h> | ||||||
|  |  #include <errno.h> | ||||||
|  | +#include <stdbool.h>
 | ||||||
|  |  #include <stdio.h> | ||||||
|  |  #include <stdlib.h> | ||||||
|  |  #include <string.h> | ||||||
|  | @@ -61,7 +62,8 @@ s390x(struct fetch_context *ctx)
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | -fetch_register_banks(struct process *proc, struct fetch_context *ctx)
 | ||||||
|  | +fetch_register_banks(struct process *proc, struct fetch_context *ctx,
 | ||||||
|  | +		     bool syscall_enter)
 | ||||||
|  |  { | ||||||
|  |  	ptrace_area parea; | ||||||
|  |  	parea.len = sizeof(ctx->regs); | ||||||
|  | @@ -72,15 +74,20 @@ fetch_register_banks(struct process *proc, struct fetch_context *ctx)
 | ||||||
|  |  			strerror(errno)); | ||||||
|  |  		return -1; | ||||||
|  |  	} | ||||||
|  | +
 | ||||||
|  | +	if (syscall_enter)
 | ||||||
|  | +		ctx->regs.gprs[2] = ctx->regs.orig_gpr2;
 | ||||||
|  | +
 | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | -fetch_context_init(struct process *proc, struct fetch_context *context)
 | ||||||
|  | +fetch_context_init(struct process *proc, struct fetch_context *context,
 | ||||||
|  | +		   bool syscall_enter)
 | ||||||
|  |  { | ||||||
|  |  	context->greg = 2; | ||||||
|  |  	context->freg = 0; | ||||||
|  | -	return fetch_register_banks(proc, context);
 | ||||||
|  | +	return fetch_register_banks(proc, context, syscall_enter);
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  struct fetch_context * | ||||||
|  | @@ -89,7 +96,7 @@ arch_fetch_arg_init(enum tof type, struct process *proc,
 | ||||||
|  |  { | ||||||
|  |  	struct fetch_context *context = malloc(sizeof(*context)); | ||||||
|  |  	if (context == NULL | ||||||
|  | -	    || fetch_context_init(proc, context) < 0) {
 | ||||||
|  | +	    || fetch_context_init(proc, context, type == LT_TOF_SYSCALL) < 0) {
 | ||||||
|  |  		fprintf(stderr, "arch_fetch_arg_init: %s\n", | ||||||
|  |  			strerror(errno)); | ||||||
|  |  		free(context); | ||||||
|  | @@ -277,7 +284,7 @@ arch_fetch_retval(struct fetch_context *ctx, enum tof type,
 | ||||||
|  |  		return 0; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	if (fetch_context_init(proc, ctx) < 0)
 | ||||||
|  | +	if (fetch_context_init(proc, ctx, false) < 0)
 | ||||||
|  |  		return -1; | ||||||
|  |  	return arch_fetch_arg_next(ctx, type, proc, info, valuep); | ||||||
|  |  } | ||||||
|  | -- 
 | ||||||
							
								
								
									
										67
									
								
								SOURCES/ltrace-0.7.91-s390-irelative.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								SOURCES/ltrace-0.7.91-s390-irelative.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,67 @@ | |||||||
|  | @@ -, +, @@ 
 | ||||||
|  | ---
 | ||||||
|  |  sysdeps/linux-gnu/s390/arch.h |  2 ++ | ||||||
|  |  sysdeps/linux-gnu/s390/plt.c  | 22 ++++++++++++++++++++++ | ||||||
|  |  2 files changed, 24 insertions(+) | ||||||
|  | --- a/sysdeps/linux-gnu/s390/arch.h	
 | ||||||
|  | +++ a/sysdeps/linux-gnu/s390/arch.h	
 | ||||||
|  | @@ -1,5 +1,6 @@ 
 | ||||||
|  |  /* | ||||||
|  |   * This file is part of ltrace. | ||||||
|  | + * Copyright (C) 2013 Petr Machata, Red Hat Inc.
 | ||||||
|  |   * Copyright (C) 2001 IBM Poughkeepsie, IBM Corporation | ||||||
|  |   * | ||||||
|  |   * This program is free software; you can redistribute it and/or | ||||||
|  | @@ -25,6 +26,7 @@ 
 | ||||||
|  |  #define ARCH_HAVE_FETCH_ARG | ||||||
|  |  #define ARCH_HAVE_SIZEOF | ||||||
|  |  #define ARCH_HAVE_ALIGNOF | ||||||
|  | +#define ARCH_HAVE_ADD_PLT_ENTRY
 | ||||||
|  |   | ||||||
|  |  #define LT_ELFCLASS	ELFCLASS32 | ||||||
|  |  #define LT_ELF_MACHINE	EM_S390 | ||||||
|  | --- a/sysdeps/linux-gnu/s390/plt.c	
 | ||||||
|  | +++ a/sysdeps/linux-gnu/s390/plt.c	
 | ||||||
|  | @@ -1,5 +1,6 @@ 
 | ||||||
|  |  /* | ||||||
|  |   * This file is part of ltrace. | ||||||
|  | + * Copyright (C) 2013 Petr Machata, Red Hat Inc.
 | ||||||
|  |   * Copyright (C) 2004,2008,2009 Juan Cespedes | ||||||
|  |   * | ||||||
|  |   * This program is free software; you can redistribute it and/or | ||||||
|  | @@ -19,9 +20,12 @@ 
 | ||||||
|  |   */ | ||||||
|  |   | ||||||
|  |  #include <gelf.h> | ||||||
|  | +#include <stdbool.h>
 | ||||||
|  | +
 | ||||||
|  |  #include "proc.h" | ||||||
|  |  #include "common.h" | ||||||
|  |  #include "library.h" | ||||||
|  | +#include "trace.h"
 | ||||||
|  |   | ||||||
|  |  GElf_Addr | ||||||
|  |  arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) { | ||||||
|  | @@ -33,3 +37,21 @@ sym2addr(struct process *proc, struct library_symbol *sym)
 | ||||||
|  |  { | ||||||
|  |  	return sym->enter_addr; | ||||||
|  |  } | ||||||
|  | +
 | ||||||
|  | +enum plt_status
 | ||||||
|  | +arch_elf_add_plt_entry(struct process *proc, struct ltelf *lte,
 | ||||||
|  | +		       const char *a_name, GElf_Rela *rela, size_t ndx,
 | ||||||
|  | +		       struct library_symbol **ret)
 | ||||||
|  | +{
 | ||||||
|  | +#ifdef R_390_IRELATIVE
 | ||||||
|  | +	bool irelative = GELF_R_TYPE(rela->r_info) == R_390_IRELATIVE;
 | ||||||
|  | +#else
 | ||||||
|  | +	bool irelative = false;
 | ||||||
|  | +#endif
 | ||||||
|  | +
 | ||||||
|  | +	if (irelative)
 | ||||||
|  | +		return linux_elf_add_plt_entry_irelative(proc, lte, rela,
 | ||||||
|  | +							 ndx, ret);
 | ||||||
|  | +
 | ||||||
|  | +	return PLT_DEFAULT;
 | ||||||
|  | +}
 | ||||||
|  | -- 
 | ||||||
							
								
								
									
										96
									
								
								SOURCES/ltrace-0.7.91-tautology.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								SOURCES/ltrace-0.7.91-tautology.patch
									
									
									
									
									
										Normal 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~ | ||||||
							
								
								
									
										48
									
								
								SOURCES/ltrace-0.7.91-testsuite-includes-2.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								SOURCES/ltrace-0.7.91-testsuite-includes-2.patch
									
									
									
									
									
										Normal 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 | ||||||
|  | 
 | ||||||
							
								
								
									
										216
									
								
								SOURCES/ltrace-0.7.91-testsuite-includes.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								SOURCES/ltrace-0.7.91-testsuite-includes.patch
									
									
									
									
									
										Normal 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 | ||||||
|  | 
 | ||||||
							
								
								
									
										422
									
								
								SOURCES/ltrace-0.7.91-unwind-elfutils.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										422
									
								
								SOURCES/ltrace-0.7.91-unwind-elfutils.patch
									
									
									
									
									
										Normal 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", | ||||||
							
								
								
									
										101
									
								
								SOURCES/ltrace-0.7.91-x86-plt_map.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								SOURCES/ltrace-0.7.91-x86-plt_map.patch
									
									
									
									
									
										Normal 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(<e->arch.plt_map, unsigned int); | ||||||
|  |   | ||||||
|  | +	if (vect_reserve(<e->arch.plt_map, vect_size(<e->plt_relocs)) < 0) {
 | ||||||
|  | +	fail:
 | ||||||
|  | +		arch_elf_destroy(lte);
 | ||||||
|  | +		return -1;
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  | +	{
 | ||||||
|  | +		unsigned int i, sz = vect_size(<e->plt_relocs);
 | ||||||
|  | +		for (i = 0; i < sz; ++i)
 | ||||||
|  | +			vect_pushback (<e->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(<e->plt_relocs); ++i) {
 | ||||||
|  | +	unsigned int i, sz = vect_size(<e->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(<e->arch.plt_map, &reloc_arg) < 0) {
 | ||||||
|  | -			arch_elf_destroy(lte);
 | ||||||
|  | -			return -1;
 | ||||||
|  | -		}
 | ||||||
|  | +		*VECT_ELEMENT(<e->arch.plt_map, unsigned int, reloc_arg) = i;
 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	return 0; | ||||||
|  | -- 
 | ||||||
|  | 2.1.0 | ||||||
|  | 
 | ||||||
							
								
								
									
										32
									
								
								SOURCES/ltrace-0.7.91-x86-unused_label.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								SOURCES/ltrace-0.7.91-x86-unused_label.patch
									
									
									
									
									
										Normal 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(<e->arch.plt_map, unsigned int); | ||||||
|  |   | ||||||
|  |  	if (vect_reserve(<e->arch.plt_map, vect_size(<e->plt_relocs)) < 0) { | ||||||
|  | -	fail:
 | ||||||
|  |  		arch_elf_destroy(lte); | ||||||
|  |  		return -1; | ||||||
|  |  	} | ||||||
|  | -- 
 | ||||||
|  | 2.1.0 | ||||||
|  | 
 | ||||||
							
								
								
									
										156
									
								
								SOURCES/ltrace-0.7.91-x86_64-irelative.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								SOURCES/ltrace-0.7.91-x86_64-irelative.patch
									
									
									
									
									
										Normal 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(<e->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(<e->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(<e->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(<e->arch.plt_map, &reloc_arg) < 0) {
 | ||||||
|  | +			arch_elf_destroy(lte);
 | ||||||
|  | +			return -1;
 | ||||||
|  | +		}
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  | +	return 0;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +void
 | ||||||
|  | +arch_elf_destroy(struct ltelf *lte)
 | ||||||
|  | +{
 | ||||||
|  | +	VECT_DESTROY(<e->arch.plt_map, uint32_t, NULL, NULL);
 | ||||||
|  | +}
 | ||||||
|  | -- 
 | ||||||
							
								
								
									
										12
									
								
								SOURCES/ltrace-rh1307754.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								SOURCES/ltrace-rh1307754.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | |||||||
|  | diff -Nrup a/testsuite/ltrace.main/system_calls.exp b/testsuite/ltrace.main/system_calls.exp
 | ||||||
|  | --- a/testsuite/ltrace.main/system_calls.exp	2016-02-17 19:39:51.433134376 -0700
 | ||||||
|  | +++ b/testsuite/ltrace.main/system_calls.exp	2016-02-17 19:40:26.220402747 -0700
 | ||||||
|  | @@ -133,7 +133,7 @@ Match [Diff [Calls [ltraceRun -L -S -- $
 | ||||||
|  |      { {^write$} == 1 } | ||||||
|  |      { {^unlink(at)?$} >= 2 } | ||||||
|  |      { {^open(at)?$} == 1 } | ||||||
|  | -    { {^(new|f)?stat(64)?$} == 1 }
 | ||||||
|  | +    { {^(new|f)?stat(64)?$} >= 1 }
 | ||||||
|  |      { {^close$} == 1 } | ||||||
|  |      { {^getcwd$} == 1 } | ||||||
|  |      { {^chdir$} == 1 } | ||||||
							
								
								
									
										20
									
								
								SOURCES/ltrace-rh1423913.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								SOURCES/ltrace-rh1423913.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | |||||||
|  | diff -Nrup a/sysdeps/linux-gnu/arm/trace.c b/sysdeps/linux-gnu/arm/trace.c
 | ||||||
|  | --- a/sysdeps/linux-gnu/arm/trace.c	2013-03-11 17:23:39.000000000 -0600
 | ||||||
|  | +++ b/sysdeps/linux-gnu/arm/trace.c	2017-02-17 09:39:42.233547101 -0700
 | ||||||
|  | @@ -155,6 +155,8 @@ arm_get_next_pcs(struct process *proc,
 | ||||||
|  |  	const unsigned cond = BITS(this_instr, 28, 31); | ||||||
|  |  	const unsigned opcode = BITS(this_instr, 24, 27); | ||||||
|  |   | ||||||
|  | +	uint32_t operand1, operand2, result = 0;
 | ||||||
|  | +
 | ||||||
|  |  	if (cond == COND_NV) | ||||||
|  |  		switch (opcode) { | ||||||
|  |  			arch_addr_t addr; | ||||||
|  | @@ -170,7 +172,6 @@ arm_get_next_pcs(struct process *proc,
 | ||||||
|  |  		} | ||||||
|  |  	else | ||||||
|  |  		switch (opcode) { | ||||||
|  | -			uint32_t operand1, operand2, result = 0;
 | ||||||
|  |  		case 0x0: | ||||||
|  |  		case 0x1:			/* data processing */ | ||||||
|  |  		case 0x2: | ||||||
							
								
								
									
										186
									
								
								SPECS/ltrace.spec
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								SPECS/ltrace.spec
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,186 @@ | |||||||
|  | %global __python /usr/bin/python3 | ||||||
|  | %{?scl:%{?scl_package:%scl_package ltrace}} | ||||||
|  | 
 | ||||||
|  | Summary: Tracks runtime library calls from dynamically linked executables | ||||||
|  | Name: %{?scl_prefix}ltrace | ||||||
|  | Version: 0.7.91 | ||||||
|  | Release: 1%{?dist} | ||||||
|  | URL: http://ltrace.alioth.debian.org/ | ||||||
|  | License: GPLv2+ | ||||||
|  | 
 | ||||||
|  | BuildRequires: elfutils-devel dejagnu | ||||||
|  | BuildRequires: libselinux-devel | ||||||
|  | BuildRequires: autoconf automake libtool | ||||||
|  | 
 | ||||||
|  | # Note: this URL needs to be updated for each release, as the file | ||||||
|  | # number changes for each file.  Full list of released files is at: | ||||||
|  | #  https://alioth.debian.org/frs/?group_id=30892 | ||||||
|  | Source: ltrace-%{version}.tar.bz2 | ||||||
|  | 
 | ||||||
|  | # Merge of several upstream commits that fixes compilation on ARM. | ||||||
|  | Patch0: ltrace-0.7.91-arm.patch | ||||||
|  | 
 | ||||||
|  | # Upstream patch that fixes accounting of exec, __libc_start_main and | ||||||
|  | # others in -c output. | ||||||
|  | Patch1: ltrace-0.7.91-account_execl.patch | ||||||
|  | 
 | ||||||
|  | # Upstream patch that fixes interpretation of PLT on x86_64 when | ||||||
|  | # IRELATIVE slots are present. | ||||||
|  | Patch2: ltrace-0.7.91-x86_64-irelative.patch | ||||||
|  | 
 | ||||||
|  | # Upstream patch that fixes fetching of system call arguments on s390. | ||||||
|  | Patch3: ltrace-0.7.91-s390-fetch-syscall.patch | ||||||
|  | 
 | ||||||
|  | # Upstream patch that enables tracing of IRELATIVE PLT slots on s390. | ||||||
|  | Patch4: ltrace-0.7.91-s390-irelative.patch | ||||||
|  | 
 | ||||||
|  | # Fix for a regression in tracing across fork.  Upstream patch. | ||||||
|  | Patch5: ltrace-0.7.91-ppc64-fork.patch | ||||||
|  | 
 | ||||||
|  | # Fix crashing a prelinked PPC64 binary which makes PLT calls through | ||||||
|  | # slots that ltrace doesn't trace. | ||||||
|  | # https://bugzilla.redhat.com/show_bug.cgi?id=1051221 | ||||||
|  | Patch6: ltrace-0.7.91-breakpoint-on_install.patch | ||||||
|  | Patch7: ltrace-0.7.91-ppc64-unprelink.patch | ||||||
|  | 
 | ||||||
|  | # Man page nits.  Backport of an upstream patch. | ||||||
|  | Patch8: ltrace-0.7.91-man.patch | ||||||
|  | 
 | ||||||
|  | # https://bugzilla.redhat.com/show_bug.cgi?id=1044766 | ||||||
|  | Patch9: ltrace-0.7.91-cant_open.patch | ||||||
|  | 
 | ||||||
|  | # Support Aarch64 architecture. | ||||||
|  | Patch10: ltrace-0.7.91-aarch64.patch | ||||||
|  | 
 | ||||||
|  | # https://bugzilla.redhat.com/show_bug.cgi?id=1064406 | ||||||
|  | Patch11: ltrace-0.7.2-e_machine.patch | ||||||
|  | 
 | ||||||
|  | # Support for ppc64le, backported from upstream. | ||||||
|  | # http://anonscm.debian.org/gitweb/?p=collab-maint/ltrace.git;a=commit;h=eea4ad2cce289753aaa35b4e0258a76d8f8f367c | ||||||
|  | # https://bugzilla.redhat.com/show_bug.cgi?id=1131956 | ||||||
|  | Patch13: ltrace-0.7.91-ppc64le-support.patch | ||||||
|  | # 35a9677dc9dcb7909ebd28f30200474d7e8b660f, | ||||||
|  | # 437d2377119036346f4dbd93039c847b4cc9d0be, | ||||||
|  | # eb3993420734f091cde9a6053ca6b4edcf9ae334 | ||||||
|  | Patch14: ltrace-0.7.91-ppc64le-fixes.patch | ||||||
|  | 
 | ||||||
|  | # http://anonscm.debian.org/gitweb/?p=collab-maint/ltrace.git;a=commit;h=2e9f9f1f5d0fb223b109429b9c904504b7f638e2 | ||||||
|  | # http://anonscm.debian.org/gitweb/?p=collab-maint/ltrace.git;a=commit;h=f96635a03b3868057db5c2d7972d5533e2068345 | ||||||
|  | Patch15: ltrace-0.7.91-parser-ws_after_id.patch | ||||||
|  | 
 | ||||||
|  | # https://bugzilla.redhat.com/show_bug.cgi?id=1171165 | ||||||
|  | # http://anonscm.debian.org/cgit/collab-maint/ltrace.git/commit/?id=d8f1287b85e2c2b2ae0235809e956f4365e53c45 | ||||||
|  | # http://anonscm.debian.org/cgit/collab-maint/ltrace.git/commit/?id=d80c5371454383e3f9978622e5578cf02af8c44c | ||||||
|  | # http://anonscm.debian.org/cgit/collab-maint/ltrace.git/commit/?id=bf82100966deda9c7d26ad085d97c08126a8ae88 | ||||||
|  | Patch16: ltrace-0.7.91-ppc-bias.patch | ||||||
|  | 
 | ||||||
|  | # https://bugzilla.redhat.com/show_bug.cgi?id=1158714 | ||||||
|  | Patch17: ltrace-0.7.91-x86-plt_map.patch | ||||||
|  | Patch18: ltrace-0.7.91-x86-unused_label.patch | ||||||
|  | 
 | ||||||
|  | # https://bugzilla.redhat.com/show_bug.cgi?id=1170315 | ||||||
|  | Patch19: ltrace-0.7.91-unwind-elfutils.patch | ||||||
|  | 
 | ||||||
|  | # https://bugzilla.redhat.com/show_bug.cgi?id=1208351 | ||||||
|  | # http://anonscm.debian.org/cgit/collab-maint/ltrace.git/commit/?id=4724bd5a4a19db117a1d280b9d1a3508fd4e03fa | ||||||
|  | # http://anonscm.debian.org/cgit/collab-maint/ltrace.git/commit/?id=72ee29639c55b5942bc07c8ed0013005f8fc5a97 | ||||||
|  | Patch20: ltrace-0.7.91-multithread-no-f-1.patch | ||||||
|  | Patch21: ltrace-0.7.91-multithread-no-f-2.patch | ||||||
|  | 
 | ||||||
|  | # Fix problems with building a number of test cases. | ||||||
|  | # http://anonscm.debian.org/cgit/collab-maint/ltrace.git/commit/?id=694d19ff14017926454771cbb63a22355b72f1bf | ||||||
|  | # http://anonscm.debian.org/cgit/collab-maint/ltrace.git/commit/?id=a3a03622fb4ca9772dca13eae724a94ba1e728f4 | ||||||
|  | Patch22: ltrace-0.7.91-testsuite-includes.patch | ||||||
|  | Patch23: ltrace-0.7.91-testsuite-includes-2.patch | ||||||
|  | 
 | ||||||
|  | # https://bugzilla.redhat.com/show_bug.cgi?id=1210653 | ||||||
|  | # http://anonscm.debian.org/cgit/collab-maint/ltrace.git/commit/?id=eea6091f8672b01f7f022b0fc367e0f568225ffc | ||||||
|  | Patch24: ltrace-0.7.91-ppc64le-configure.patch | ||||||
|  | 
 | ||||||
|  | Patch25: ltrace-rh1307754.patch | ||||||
|  | 
 | ||||||
|  | # GCC now warns (errors) on "tautological compares", and readdir_r is deprecated. | ||||||
|  | Patch26: ltrace-0.7.91-tautology.patch | ||||||
|  | 
 | ||||||
|  | # ARM code has unreachable code after switch statement, move initialization | ||||||
|  | Patch27: ltrace-rh1423913.patch | ||||||
|  | 
 | ||||||
|  | # AARCH64 large parameters and syscall testsuite fixes. | ||||||
|  | Patch28: ltrace-0.7.91-aarch64-params.patch | ||||||
|  | 
 | ||||||
|  | # gcc-9 fix.  Avoid passing NULL as argument to %s | ||||||
|  | Patch29: ltrace-0.7.91-null.patch | ||||||
|  | 
 | ||||||
|  | # Adds support for CET PLTs via second-plt lookups. | ||||||
|  | Patch30: ltrace-0.7.91-cet.patch | ||||||
|  | 
 | ||||||
|  | %description | ||||||
|  | Ltrace is a debugging program which runs a specified command until the | ||||||
|  | command exits.  While the command is executing, ltrace intercepts and | ||||||
|  | records both the dynamic library calls called by the executed process | ||||||
|  | and the signals received by the executed process.  Ltrace can also | ||||||
|  | intercept and print system calls executed by the process. | ||||||
|  | 
 | ||||||
|  | You should install ltrace if you need a sysadmin tool for tracking the | ||||||
|  | execution of processes. | ||||||
|  | 
 | ||||||
|  | %prep | ||||||
|  | %setup -q -n ltrace-%{version} | ||||||
|  | %patch0 -p1 | ||||||
|  | %patch1 -p1 | ||||||
|  | %patch2 -p1 | ||||||
|  | %patch3 -p1 | ||||||
|  | %patch4 -p1 | ||||||
|  | %patch5 -p1 | ||||||
|  | %patch6 -p1 | ||||||
|  | %patch7 -p1 | ||||||
|  | %patch8 -p1 | ||||||
|  | %patch9 -p1 | ||||||
|  | %patch10 -p1 | ||||||
|  | %patch11 -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 | ||||||
|  | %patch30 -p1 | ||||||
|  | 
 | ||||||
|  | %build | ||||||
|  | autoreconf -i | ||||||
|  | %configure --docdir=%{?_pkgdocdir}%{!?_pkgdocdir:%{_docdir}/%{name}-%{version}} | ||||||
|  | make %{?_smp_mflags} | ||||||
|  | 
 | ||||||
|  | %install | ||||||
|  | make DESTDIR=$RPM_BUILD_ROOT bindir=%{_bindir} install | ||||||
|  | 
 | ||||||
|  | # The testsuite is useful for development in real world, but fails in | ||||||
|  | # koji for some reason.  Disable it, but have it handy. | ||||||
|  | %check | ||||||
|  | echo ====================TESTING========================= | ||||||
|  | timeout 180 make -k check ||: | ||||||
|  | echo ====================TESTING END===================== | ||||||
|  | 
 | ||||||
|  | %files | ||||||
|  | %defattr(-,root,root) | ||||||
|  | %doc NEWS COPYING CREDITS INSTALL README TODO | ||||||
|  | %{_bindir}/ltrace | ||||||
|  | %{_mandir}/man1/ltrace.1* | ||||||
|  | %{_mandir}/man5/ltrace.conf.5* | ||||||
|  | %{_datadir}/ltrace | ||||||
|  | 
 | ||||||
|  | %changelog | ||||||
|  | * Wed May 26 2019 DJ Delorie <dj@redhat.com> - 0.7.91-1 | ||||||
|  | - Initial sources (#1818987) | ||||||
|  | 
 | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user