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