patches/ltrace/0.5/130-fixes-by-debian.patch
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Sun Jan 17 23:06:02 2010 +0100 (2010-01-17)
changeset 1740 c57458bb354d
permissions -rw-r--r--
configure: do not require hg when configuring in an hg clone

When configuring in an hg clone, we need hg to compute the version string.
It can happen that users do not have Mercurial (eg. if they got a snapshot
rather that they did a full clone). In this case, we can still run, of
course, so simply fill the version string with a sufficiently explicit
value, that does not require hg. The date is a good candidate.
     1 This patch was vampirised from the 0.5-3.1 Debian-packaged version of ltrace,
     2 and contains the following fixes (exerpt from the Debian changelog). Moreover,
     3 you will also find an exerpt of the Debian copyright file with proper
     4 attribution.
     5 
     6 ================ Debian changelog exerpt ================
     7 ltrace (0.5-3.1) unstable; urgency=low
     8 
     9   * Non-maintainer upload.
    10   * Big thanks for Anderson Lizardo for providing patches!
    11   * Add generic support for arm targets, Closes: #176413
    12   * Save funtion arguments on arm, Closes: #462530
    13   * Add thumb instruction support, Closes: #462531
    14   * Add basic arm/eabi support, Closes: #450931
    15   * fix exec() testcase cleanup, Closes: #462532
    16   * fix memory corruption in clone() test, Closes: #462533
    17   * fix tracing child with "-p" option, Closes: #462535
    18   * Update standard, no changes
    19 
    20  -- Riku Voipio <riku.voipio@iki.fi>  Tue, 29 Jan 2008 00:26:50 +0200
    21 
    22 ltrace (0.5-3) unstable; urgency=low
    23 
    24   * Really fix compilation problems in ppc (!)
    25 
    26  -- Juan Cespedes <cespedes@debian.org>  Fri, 31 Aug 2007 19:04:03 +0200
    27 
    28 ltrace (0.5-2) unstable; urgency=low
    29 
    30   * Fixed compilation issue in ppc
    31 
    32  -- Juan Cespedes <cespedes@debian.org>  Fri, 31 Aug 2007 13:53:27 +0200
    33 
    34 ltrace (0.5-1) unstable; urgency=low
    35 
    36   * New upstream version
    37   * Remove some unneeded files in /usr/share/doc (ChangeLog, COPYING...)
    38   * Fix several typos (closes: Bug#372928)
    39   * Added more system calls to ltrace.conf
    40 
    41  -- Juan Cespedes <cespedes@debian.org>  Thu, 30 Aug 2007 14:54:44 +0200
    42 ============== End Debian changelog exerpt ==============
    43 
    44 ================ Debian copyright exerpt ================
    45 Copyrights
    46 ----------
    47 Copyright (C) 1997-2007 Juan Cespedes <cespedes@debian.org>
    48 
    49 ARMLinux port: Copyright (C) 1998 Pat Beirne <pbeirne@home.com>
    50 m68k port: Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
    51 Misc fixes: Copyright (C) 1999 Morten Eriksen <mortene@sim.no>
    52 s390 port: Copyright (C) 2001 IBM Poughkeepsie, IBM Cororation <slate@us.ibm.com>
    53 ELF hacking: Copyright (C) 1999 Silvio Cesare <silvio@big.net.au>
    54 PowerPC port: Copyright (C) 2001-2002 Anton Blanchard <anton@samba.org>
    55 SPARC port: Copyright (C) 1999 Jakub Jelinek <jakub@redhat.com>
    56 
    57 Autoconf stuff: Copyright 1992-1996 Free Software Foundation, Inc.
    58 install-sh: Copyright 1991 by the Massachusetts Institute of Technology
    59 C++ demangle: Copyright 1989-1997 Free Software Foundation, Inc.
    60 ============== End Debian copyright exerpt ==============
    61 
    62 diff -durN ltrace-0.5.orig/breakpoints.c ltrace-0.5/breakpoints.c
    63 --- ltrace-0.5.orig/breakpoints.c	2006-06-14 06:55:21.000000000 +0200
    64 +++ ltrace-0.5/breakpoints.c	2008-11-04 19:25:50.000000000 +0100
    65 @@ -53,6 +53,10 @@
    66  		if (libsym)
    67  			libsym->brkpnt = sbp;
    68  	}
    69 +#ifdef __arm__
    70 +	sbp->thumb_mode = proc->thumb_mode;
    71 +	proc->thumb_mode = 0;
    72 +#endif
    73  	sbp->enabled++;
    74  	if (sbp->enabled == 1 && proc->pid)
    75  		enable_breakpoint(proc->pid, sbp);
    76 diff -durN ltrace-0.5.orig/elf.c ltrace-0.5/elf.c
    77 --- ltrace-0.5.orig/elf.c	2006-06-14 06:55:21.000000000 +0200
    78 +++ ltrace-0.5/elf.c	2008-11-04 19:25:50.000000000 +0100
    79 @@ -464,8 +464,7 @@
    80  			if (strcmp(xptr->name, PLTs_initialized_by_here) == 0) {
    81  				if (lte->ehdr.e_entry) {
    82  					add_library_symbol (
    83 -						elf_plt2addr (lte, (void*)(long)
    84 -							lte->ehdr.e_entry),
    85 +						opd2addr (lte, lte->ehdr.e_entry),
    86  						PLTs_initialized_by_here,
    87  						lib_tail, 1, 0);
    88  					fprintf (stderr, "WARNING: Using e_ent"
    89 diff -durN ltrace-0.5.orig/etc/ltrace.conf ltrace-0.5/etc/ltrace.conf
    90 --- ltrace-0.5.orig/etc/ltrace.conf	2006-02-20 22:55:47.000000000 +0100
    91 +++ ltrace-0.5/etc/ltrace.conf	2008-11-04 19:25:50.000000000 +0100
    92 @@ -444,3 +444,81 @@
    93  int   SYS_removexattr(string,string);
    94  int   SYS_lremovexattr(string,string);
    95  int   SYS_fremovexattr(int,string);
    96 +int   SYS_chdir(string);
    97 +int   SYS_fchdir(int);
    98 +int   SYS_chmod(string,octal);
    99 +int   SYS_fchmod(int,octal);
   100 +int   SYS_chown(string,int,int);
   101 +int   SYS_fchown(int,int,int);
   102 +int   SYS_lchown(string,int,int);
   103 +int   SYS_chroot(string);
   104 +int   SYS_dup(int);
   105 +int   SYS_dup2(int,int);
   106 +int   SYS_fdatasync(int);
   107 +int   SYS_fsync(int);
   108 +int   SYS_getpriority(int,int);
   109 +int   SYS_setpriority(int,int,int);
   110 +int   SYS_getrlimit(int,addr);
   111 +int   SYS_setrlimit(int,addr);
   112 +int   SYS_gettimeofday(addr,addr);
   113 +int   SYS_settimeofday(addr,addr);
   114 +int   SYS_setfsgid(int);
   115 +int   SYS_setfsuid(int);
   116 +int   SYS_getuid(void);
   117 +int   SYS_setuid(int);
   118 +int   SYS_getgid(void);
   119 +int   SYS_setgid(int);
   120 +int   SYS_getsid(int);
   121 +int   SYS_setsid(int);
   122 +int   SYS_setreuid(int,int);
   123 +int   SYS_setregid(int,int);
   124 +int   SYS_geteuid(void);
   125 +int   SYS_getegid(void);
   126 +int   SYS_setpgid(int,int);
   127 +int   SYS_getresuid(addr,addr,addr);
   128 +int   SYS_setresuid(int,int,int);
   129 +int   SYS_getresgid(addr,addr,addr);
   130 +int   SYS_setresgid(int,int,int);
   131 +int   SYS_kill(int,int);
   132 +int   SYS_link(string,string);
   133 +int   SYS_madvise(addr,ulong,int);
   134 +int   SYS_mkdir(string,octal);
   135 +int   SYS_mknod(string,octal,int);
   136 +int   SYS_msync(addr,ulong,int);
   137 +int   SYS_nice(int);
   138 +int   SYS_poll(addr,uint,int);
   139 +int   SYS_readdir(uint,addr,uint);
   140 +int   SYS_readlink(string,string,ulong);
   141 +int   SYS_reboot(int,int,int,addr);
   142 +int   SYS_rename(string,string);
   143 +int   SYS_rmdir(string);
   144 +int   SYS_sigaltstack(addr,addr);
   145 +int   SYS_statfs(string,addr);
   146 +int   SYS_fstatfs(int,addr);
   147 +int   SYS_fstat(int,addr);
   148 +int   SYS_lstat(string,addr);
   149 +int   SYS_stime(addr);
   150 +int   SYS_symlink(string, string);
   151 +int   SYS_sysinfo(addr);
   152 +int   SYS_syslog(int,string,int);
   153 +int   SYS_truncate(string,long);
   154 +int   SYS_ftruncate(int,long);
   155 +int   SYS_mount(string,string,string,ulong,addr);
   156 +int   SYS_umount(string);
   157 +int   SYS_umount2(string,int);
   158 +int   SYS_unlink(string);
   159 +int   SYS_utime(string,addr);
   160 +long  SYS_lseek(int,long,int);
   161 +addr  SYS_signal(int,addr);
   162 +int   SYS_sigaction(int,addr,addr);
   163 +int   SYS_pause(void);
   164 +int   SYS_sigpending(addr);
   165 +int   SYS_sigprocmask(int,addr,addr);
   166 +int   SYS_sigqueue(int,int,addr);
   167 +int   SYS_sigsuspend(addr);
   168 +int   SYS_wait(addr);
   169 +int   SYS_waitpid(int,addr,int);
   170 +ulong SYS_readv(int,addr,int);
   171 +ulong SYS_writev(int,addr,int);
   172 +int   SYS_mprotect(addr,int,int);
   173 +int   SYS_access(string,octal);
   174 diff -durN ltrace-0.5.orig/ltrace.1 ltrace-0.5/ltrace.1
   175 --- ltrace-0.5.orig/ltrace.1	2006-06-16 03:15:18.000000000 +0200
   176 +++ ltrace-0.5/ltrace.1	2008-11-04 19:25:50.000000000 +0100
   177 @@ -30,7 +30,7 @@
   178  .TP
   179  .I \-C, \-\-demangle
   180  Decode (demangle) low-level symbol names into user-level names.
   181 -Besides removing any initial underscore prepended by the system,
   182 +Besides removing any initial underscore prefix used by the system,
   183  this makes C++ function names readable.
   184  .TP
   185  .I \-d, \-\-debug
   186 diff -durN ltrace-0.5.orig/ltrace.c ltrace-0.5/ltrace.c
   187 --- ltrace-0.5.orig/ltrace.c	2006-02-20 22:48:07.000000000 +0100
   188 +++ ltrace-0.5/ltrace.c	2008-11-04 19:25:50.000000000 +0100
   189 @@ -54,6 +54,9 @@
   190  {
   191  	exiting = 1;
   192  	debug(1, "Received interrupt signal; exiting...");
   193 +	if (opt_o) {
   194 +		fclose(output);
   195 +	}
   196  	signal(SIGINT, SIG_IGN);
   197  	signal(SIGTERM, SIG_IGN);
   198  	signal(SIGALRM, signal_alarm);
   199 @@ -74,6 +77,9 @@
   200  	if (opt_c) {
   201  		show_summary();
   202  	}
   203 +	if (opt_o) {
   204 +		fclose(output);
   205 +	}
   206  }
   207  
   208  static void guess_cols(void)
   209 diff -durN ltrace-0.5.orig/ltrace.h ltrace-0.5/ltrace.h
   210 --- ltrace-0.5.orig/ltrace.h	2006-06-14 06:55:21.000000000 +0200
   211 +++ ltrace-0.5/ltrace.h	2008-11-04 19:25:50.000000000 +0100
   212 @@ -26,6 +26,9 @@
   213  	unsigned char orig_value[BREAKPOINT_LENGTH];
   214  	int enabled;
   215  	struct library_symbol *libsym;
   216 +#ifdef __arm__
   217 +	int thumb_mode;
   218 +#endif
   219  };
   220  
   221  enum arg_type {
   222 @@ -119,6 +122,9 @@
   223  	void *arch_ptr;
   224  	short e_machine;
   225  	short need_to_reinitialize_breakpoints;
   226 +#ifdef __arm__
   227 +	int thumb_mode; /* ARM execution mode: 0: ARM mode, 1: Thumb mode */
   228 +#endif
   229  
   230  	/* output: */
   231  	enum tof type_being_displayed;
   232 @@ -136,12 +142,14 @@
   233  		LT_EV_EXIT_SIGNAL,
   234  		LT_EV_SYSCALL,
   235  		LT_EV_SYSRET,
   236 +		LT_EV_ARCH_SYSCALL,
   237 +		LT_EV_ARCH_SYSRET,
   238  		LT_EV_BREAKPOINT
   239  	} thing;
   240  	union {
   241  		int ret_val;	/* _EV_EXIT */
   242  		int signum;	/* _EV_SIGNAL, _EV_EXIT_SIGNAL */
   243 -		int sysnum;	/* _EV_SYSCALL, _EV_SYSRET */
   244 +		int sysnum;	/* _EV_SYSCALL, _EV_SYSRET, _EV_ARCH_SYSCALL, _EV_ARCH_SYSRET */
   245  		void *brk_addr;	/* _EV_BREAKPOINT */
   246  	} e_un;
   247  };
   248 diff -durN ltrace-0.5.orig/options.c ltrace-0.5/options.c
   249 --- ltrace-0.5.orig/options.c	2006-04-24 22:06:23.000000000 +0200
   250 +++ ltrace-0.5/options.c	2008-11-04 19:25:50.000000000 +0100
   251 @@ -42,6 +42,7 @@
   252  #endif
   253  int opt_n = 0;			/* indent trace output according to program flow */
   254  int opt_T = 0;			/* show the time spent inside each call */
   255 +int opt_o = 0;			/* output to a specific file */
   256  
   257  /* List of pids given to option -p: */
   258  struct opt_p_t *opt_p = NULL;	/* attach to process with a given pid */
   259 @@ -274,6 +275,7 @@
   260  			opt_n = atoi(optarg);
   261  			break;
   262  		case 'o':
   263 +			opt_o++;
   264  			output = fopen(optarg, "w");
   265  			if (!output) {
   266  				fprintf(stderr,
   267 diff -durN ltrace-0.5.orig/options.h ltrace-0.5/options.h
   268 --- ltrace-0.5.orig/options.h	2006-03-13 18:43:13.000000000 +0100
   269 +++ ltrace-0.5/options.h	2008-11-04 19:25:50.000000000 +0100
   270 @@ -20,6 +20,7 @@
   271  extern int opt_C;		/* Demanglelow-level symbol names into user-level names */
   272  extern int opt_n;		/* indent trace output according to program flow */
   273  extern int opt_T;		/* show the time spent inside each call */
   274 +extern int opt_o;		/* output to a specific file */
   275  
   276  struct opt_p_t {
   277  	pid_t pid;
   278 diff -durN ltrace-0.5.orig/process_event.c ltrace-0.5/process_event.c
   279 --- ltrace-0.5.orig/process_event.c	2006-06-14 06:55:21.000000000 +0200
   280 +++ ltrace-0.5/process_event.c	2008-11-04 19:25:50.000000000 +0100
   281 @@ -24,7 +24,9 @@
   282  static void process_exit(struct event *event);
   283  static void process_exit_signal(struct event *event);
   284  static void process_syscall(struct event *event);
   285 +static void process_arch_syscall(struct event *event);
   286  static void process_sysret(struct event *event);
   287 +static void process_arch_sysret(struct event *event);
   288  static void process_breakpoint(struct event *event);
   289  static void remove_proc(struct process *proc);
   290  
   291 @@ -81,6 +83,24 @@
   292  	}
   293  }
   294  
   295 +static char *arch_sysname(struct process *proc, int sysnum)
   296 +{
   297 +	static char result[128];
   298 +	static char *arch_syscalent[] = {
   299 +#include "arch_syscallent.h"
   300 +	};
   301 +	int nsyscals = sizeof arch_syscalent / sizeof arch_syscalent[0];
   302 +
   303 +	if (sysnum < 0 || sysnum >= nsyscals) {
   304 +		sprintf(result, "ARCH_%d", sysnum);
   305 +		return result;
   306 +	} else {
   307 +		sprintf(result, "ARCH_%s",
   308 +			arch_syscalent[sysnum]);
   309 +		return result;
   310 +	}
   311 +}
   312 +
   313  void process_event(struct event *event)
   314  {
   315  	switch (event->thing) {
   316 @@ -115,6 +135,18 @@
   317  		      event->e_un.sysnum);
   318  		process_sysret(event);
   319  		return;
   320 +	case LT_EV_ARCH_SYSCALL:
   321 +		debug(1, "event: arch_syscall (%s [%d])",
   322 +		      arch_sysname(event->proc, event->e_un.sysnum),
   323 +		      event->e_un.sysnum);
   324 +		process_arch_syscall(event);
   325 +		return;
   326 +	case LT_EV_ARCH_SYSRET:
   327 +		debug(1, "event: arch_sysret (%s [%d])",
   328 +		      arch_sysname(event->proc, event->e_un.sysnum),
   329 +		      event->e_un.sysnum);
   330 +		process_arch_sysret(event);
   331 +		return;
   332  	case LT_EV_BREAKPOINT:
   333  		debug(1, "event: breakpoint");
   334  		process_breakpoint(event);
   335 @@ -195,6 +227,19 @@
   336  	continue_process(event->proc->pid);
   337  }
   338  
   339 +static void process_arch_syscall(struct event *event)
   340 +{
   341 +	if (opt_S) {
   342 +		output_left(LT_TOF_SYSCALL, event->proc,
   343 +			    arch_sysname(event->proc, event->e_un.sysnum));
   344 +	}
   345 +	if (event->proc->breakpoints_enabled == 0) {
   346 +		enable_all_breakpoints(event->proc);
   347 +	}
   348 +	callstack_push_syscall(event->proc, 0xf0000 + event->e_un.sysnum);
   349 +	continue_process(event->proc->pid);
   350 +}
   351 +
   352  struct timeval current_time_spent;
   353  
   354  static void calc_time_spent(struct process *proc)
   355 @@ -257,6 +302,19 @@
   356  	continue_process(event->proc->pid);
   357  }
   358  
   359 +static void process_arch_sysret(struct event *event)
   360 +{
   361 +	if (opt_T || opt_c) {
   362 +		calc_time_spent(event->proc);
   363 +	}
   364 +	callstack_pop(event->proc);
   365 +	if (opt_S) {
   366 +		output_right(LT_TOF_SYSCALLR, event->proc,
   367 +			     arch_sysname(event->proc, event->e_un.sysnum));
   368 +	}
   369 +	continue_process(event->proc->pid);
   370 +}
   371 +
   372  static void process_breakpoint(struct event *event)
   373  {
   374  	int i, j;
   375 diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/Makefile ltrace-0.5/sysdeps/linux-gnu/Makefile
   376 --- ltrace-0.5.orig/sysdeps/linux-gnu/Makefile	2008-11-04 19:25:11.000000000 +0100
   377 +++ ltrace-0.5/sysdeps/linux-gnu/Makefile	2008-11-04 19:25:50.000000000 +0100
   378 @@ -2,7 +2,7 @@
   379  
   380  OBJ		=	trace.o proc.o breakpoint.o
   381  
   382 -all:		sysdep.h signalent.h syscallent.h signalent1.h syscallent1.h ../sysdep.o
   383 +all:		sysdep.h signalent.h syscallent.h arch_syscallent.h signalent1.h syscallent1.h ../sysdep.o
   384  
   385  sysdep.h:	$(ARCH)/arch.h
   386  		cat $(ARCH)/arch.h > sysdep.h
   387 @@ -26,6 +26,13 @@
   388  			> syscallent1.h; \
   389  		fi
   390  
   391 +arch_syscallent.h:
   392 +		if [ -f $(ARCH)/arch_syscallent.h ]; then \
   393 +			cp $(ARCH)/arch_syscallent.h arch_syscallent.h; \
   394 +		else \
   395 +			> arch_syscallent.h; \
   396 +		fi
   397 +
   398  ../sysdep.o:	os.o $(ARCH)/arch.o
   399  		$(CC) -nostdlib -r -o ../sysdep.o os.o $(ARCH)/arch.o
   400  
   401 @@ -37,7 +44,7 @@
   402  
   403  clean:
   404  		$(MAKE) -C $(ARCH) clean
   405 -		rm -f $(OBJ) sysdep.h signalent.h signalent1.h syscallent.h
   406 +		rm -f $(OBJ) sysdep.h signalent.h signalent1.h syscallent.h arch_syscallent.h
   407  		rm -f syscallent1.h os.o sysdep.o ../sysdep.o
   408  
   409  dummy:
   410 diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/arch_mksyscallent ltrace-0.5/sysdeps/linux-gnu/arch_mksyscallent
   411 --- ltrace-0.5.orig/sysdeps/linux-gnu/arch_mksyscallent	1970-01-01 01:00:00.000000000 +0100
   412 +++ ltrace-0.5/sysdeps/linux-gnu/arch_mksyscallent	2008-11-04 19:25:50.000000000 +0100
   413 @@ -0,0 +1,43 @@
   414 +#!/usr/bin/awk -f
   415 +
   416 +# hack expression to generate arch_syscallent.h from <asm/unistd.h>
   417 +# It reads from stdin and writes to stdout
   418 +# Currently (linux-2.6.16), it works OK on arm
   419 +# It is untested in other architectures
   420 +
   421 +BEGIN {
   422 +	max=0;
   423 +	FS="[ \t\n()+]+";
   424 +}
   425 +
   426 +{
   427 +#	printf("/%s/%s/%s/%s/\n", $1, $2, $3, $4);
   428 +	if (($1 ~ /^#define$/) && ($2 ~ /^__[A-Z]+_NR_/)) {
   429 +		sub(/^__[A-Z]+_NR_/,"",$2);
   430 +		if (($3>=0) && ($3<=1000)) {
   431 +			SYSCALL[$3]=$2;
   432 +			if ($3 > max) {
   433 +				max=$3;
   434 +			}
   435 +		} else if (($3 ~ /^__[A-Z]+_NR_BASE$/) && ($4>=0) && ($4<=1000)) {
   436 +			SYSCALL[$4]=$2;
   437 +			if ($4 > max) {
   438 +				max=$4;
   439 +			}
   440 +		}
   441 +	}
   442 +}
   443 +
   444 +END {
   445 +	for(i=0; i<=max; i++) {
   446 +		if (!SYSCALL[i]) {
   447 +			SYSCALL[i] = i;
   448 +		}
   449 +		pad = 32 - length(SYSCALL[i]);
   450 +		if (pad<1) {
   451 +			pad=1;
   452 +		}
   453 +		printf("\t\"%s\",%*s/* %d */\n", SYSCALL[i], pad, "", i);
   454 +	}
   455 +}
   456 +
   457 diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/arm/Makefile ltrace-0.5/sysdeps/linux-gnu/arm/Makefile
   458 --- ltrace-0.5.orig/sysdeps/linux-gnu/arm/Makefile	2006-02-20 22:44:45.000000000 +0100
   459 +++ ltrace-0.5/sysdeps/linux-gnu/arm/Makefile	2008-11-04 19:25:50.000000000 +0100
   460 @@ -1,4 +1,4 @@
   461 -OBJ	=	trace.o regs.o plt.o
   462 +OBJ	=	trace.o regs.o plt.o breakpoint.o
   463  
   464  all:		arch.o
   465  
   466 diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/arm/arch.h ltrace-0.5/sysdeps/linux-gnu/arm/arch.h
   467 --- ltrace-0.5.orig/sysdeps/linux-gnu/arm/arch.h	2006-04-24 22:06:23.000000000 +0200
   468 +++ ltrace-0.5/sysdeps/linux-gnu/arm/arch.h	2008-11-04 19:25:50.000000000 +0100
   469 @@ -1,5 +1,10 @@
   470 -#define BREAKPOINT_VALUE { 0x01, 0x00, 0x9f, 0xef }
   471 +#define ARCH_HAVE_ENABLE_BREAKPOINT 1
   472 +#define ARCH_HAVE_DISABLE_BREAKPOINT 1
   473 +
   474 +#define BREAKPOINT_VALUE { 0xf0, 0x01, 0xf0, 0xe7 }
   475  #define BREAKPOINT_LENGTH 4
   476 +#define THUMB_BREAKPOINT_VALUE { 0x01, 0xde }
   477 +#define THUMB_BREAKPOINT_LENGTH 2
   478  #define DECR_PC_AFTER_BREAK 0
   479  
   480  #define LT_ELFCLASS	ELFCLASS32
   481 diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/arm/arch_syscallent.h ltrace-0.5/sysdeps/linux-gnu/arm/arch_syscallent.h
   482 --- ltrace-0.5.orig/sysdeps/linux-gnu/arm/arch_syscallent.h	1970-01-01 01:00:00.000000000 +0100
   483 +++ ltrace-0.5/sysdeps/linux-gnu/arm/arch_syscallent.h	2008-11-04 19:25:50.000000000 +0100
   484 @@ -0,0 +1,6 @@
   485 +	"0",                               /* 0 */
   486 +	"breakpoint",                      /* 1 */
   487 +	"cacheflush",                      /* 2 */
   488 +	"usr26",                           /* 3 */
   489 +	"usr32",                           /* 4 */
   490 +	"set_tls",                         /* 5 */
   491 diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/arm/breakpoint.c ltrace-0.5/sysdeps/linux-gnu/arm/breakpoint.c
   492 --- ltrace-0.5.orig/sysdeps/linux-gnu/arm/breakpoint.c	1970-01-01 01:00:00.000000000 +0100
   493 +++ ltrace-0.5/sysdeps/linux-gnu/arm/breakpoint.c	2008-11-04 19:25:50.000000000 +0100
   494 @@ -0,0 +1,86 @@
   495 +/*
   496 + * This file is part of ltrace.
   497 + *
   498 + * Copyright (C) 2007 by Instituto Nokia de Tecnologia (INdT)
   499 + *
   500 + * Author: Anderson Lizardo <anderson.lizardo@indt.org.br>
   501 + *
   502 + * This program is free software; you can redistribute it and/or
   503 + * modify it under the terms of the GNU General Public License
   504 + * version 2 as published by the Free Software Foundation.
   505 + *
   506 + * This program is distributed in the hope that it will be useful, but
   507 + * WITHOUT ANY WARRANTY; without even the implied warranty of
   508 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   509 + * General Public License for more details.
   510 + *
   511 + * You should have received a copy of the GNU General Public License
   512 + * along with this program; if not, write to the Free Software
   513 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
   514 + * 02110-1301 USA
   515 + *
   516 + * Modified from sysdeps/linux-gnu/breakpoint.c and added ARM Thumb support.
   517 +*/
   518 +
   519 +#include <sys/ptrace.h>
   520 +#include "config.h"
   521 +#include "arch.h"
   522 +#include "options.h"
   523 +#include "output.h"
   524 +#include "debug.h"
   525 +
   526 +void arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp)
   527 +{
   528 +	unsigned int i, j;
   529 +	const unsigned char break_insn[] = BREAKPOINT_VALUE;
   530 +	const unsigned char thumb_break_insn[] = THUMB_BREAKPOINT_VALUE;
   531 +
   532 +	debug(1, "arch_enable_breakpoint(%d,%p)", pid, sbp->addr);
   533 +
   534 +	for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
   535 +		long a =
   536 +		    ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long),
   537 +			   0);
   538 +		unsigned char *bytes = (unsigned char *)&a;
   539 +
   540 +		debug(2, "current = 0x%lx, orig_value = 0x%lx, thumb_mode = %d", a, *(long *)&sbp->orig_value, sbp->thumb_mode);
   541 +		for (j = 0;
   542 +		     j < sizeof(long)
   543 +		     && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
   544 +
   545 +			sbp->orig_value[i * sizeof(long) + j] = bytes[j];
   546 +			if (!sbp->thumb_mode) {
   547 +				bytes[j] = break_insn[i * sizeof(long) + j];
   548 +			}
   549 +			else if (j < THUMB_BREAKPOINT_LENGTH) {
   550 +				bytes[j] = thumb_break_insn[i * sizeof(long) + j];
   551 +			}
   552 +		}
   553 +		ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
   554 +	}
   555 +}
   556 +
   557 +void arch_disable_breakpoint(pid_t pid, const struct breakpoint *sbp)
   558 +{
   559 +	unsigned int i, j;
   560 +	const unsigned char break_insn[] = BREAKPOINT_VALUE;
   561 +	const unsigned char thumb_break_insn[] = THUMB_BREAKPOINT_VALUE;
   562 +
   563 +	debug(1, "arch_disable_breakpoint(%d,%p)", pid, sbp->addr);
   564 +
   565 +	for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
   566 +		long a =
   567 +		    ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long),
   568 +			   0);
   569 +		unsigned char *bytes = (unsigned char *)&a;
   570 +
   571 +		debug(2, "current = 0x%lx, orig_value = 0x%lx, thumb_mode = %d", a, *(long *)&sbp->orig_value, sbp->thumb_mode);
   572 +		for (j = 0;
   573 +		     j < sizeof(long)
   574 +		     && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
   575 +
   576 +			bytes[j] = sbp->orig_value[i * sizeof(long) + j];
   577 +		}
   578 +		ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
   579 +	}
   580 +}
   581 diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/arm/ptrace.h ltrace-0.5/sysdeps/linux-gnu/arm/ptrace.h
   582 --- ltrace-0.5.orig/sysdeps/linux-gnu/arm/ptrace.h	2006-02-20 22:44:45.000000000 +0100
   583 +++ ltrace-0.5/sysdeps/linux-gnu/arm/ptrace.h	2008-11-04 19:25:50.000000000 +0100
   584 @@ -1 +1,9 @@
   585  #include <sys/ptrace.h>
   586 +#include <asm/ptrace.h>
   587 +
   588 +typedef struct {
   589 +	int valid;
   590 +	struct pt_regs regs;
   591 +	long func_arg[5];
   592 +	long sysc_arg[5];
   593 +} proc_archdep;
   594 diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/arm/regs.c ltrace-0.5/sysdeps/linux-gnu/arm/regs.c
   595 --- ltrace-0.5.orig/sysdeps/linux-gnu/arm/regs.c	2006-02-20 22:48:07.000000000 +0100
   596 +++ ltrace-0.5/sysdeps/linux-gnu/arm/regs.c	2008-11-04 19:25:50.000000000 +0100
   597 @@ -39,5 +39,10 @@
   598   * a CISC architecture; in our case, we don't need that */
   599  void *get_return_addr(struct process *proc, void *stack_pointer)
   600  {
   601 -	return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, off_lr, 0);
   602 +	long addr = ptrace(PTRACE_PEEKUSER, proc->pid, off_lr, 0);
   603 +
   604 +	proc->thumb_mode = addr & 1;
   605 +	if (proc->thumb_mode)
   606 +		addr &= ~1;
   607 +	return (void *)addr;
   608  }
   609 diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/arm/trace.c ltrace-0.5/sysdeps/linux-gnu/arm/trace.c
   610 --- ltrace-0.5.orig/sysdeps/linux-gnu/arm/trace.c	2006-02-20 22:48:07.000000000 +0100
   611 +++ ltrace-0.5/sysdeps/linux-gnu/arm/trace.c	2008-11-04 19:25:50.000000000 +0100
   612 @@ -2,6 +2,7 @@
   613  #include "config.h"
   614  #endif
   615  
   616 +#include <string.h>
   617  #include <sys/types.h>
   618  #include <sys/wait.h>
   619  #include <signal.h>
   620 @@ -9,6 +10,8 @@
   621  #include <asm/ptrace.h>
   622  
   623  #include "ltrace.h"
   624 +#include "output.h"
   625 +#include "ptrace.h"
   626  
   627  #if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
   628  # define PTRACE_PEEKUSER PTRACE_PEEKUSR
   629 @@ -18,19 +21,25 @@
   630  # define PTRACE_POKEUSER PTRACE_POKEUSR
   631  #endif
   632  
   633 -/* syscall tracing protocol: ArmLinux
   634 - on the way in, ip is 0
   635 - on the way out, ip is non-zero
   636 -*/
   637  #define off_r0 0
   638 +#define off_r7 28
   639  #define off_ip 48
   640  #define off_pc 60
   641  
   642  void get_arch_dep(struct process *proc)
   643  {
   644 +	proc_archdep *a;
   645 +
   646 +	if (!proc->arch_ptr)
   647 +		proc->arch_ptr = (void *)malloc(sizeof(proc_archdep));
   648 +	a = (proc_archdep *) (proc->arch_ptr);
   649 +	a->valid = (ptrace(PTRACE_GETREGS, proc->pid, 0, &a->regs) >= 0);
   650  }
   651  
   652 -/* Returns 1 if syscall, 2 if sysret, 0 otherwise.
   653 +/* Returns 0 if not a syscall,
   654 + *         1 if syscall entry, 2 if syscall exit,
   655 + *         3 if arch-specific syscall entry, 4 if arch-specific syscall exit,
   656 + *         -1 on error.
   657   */
   658  int syscall_p(struct process *proc, int status, int *sysnum)
   659  {
   660 @@ -40,19 +49,39 @@
   661  		int pc = ptrace(PTRACE_PEEKUSER, proc->pid, off_pc, 0);
   662  		/* fetch the SWI instruction */
   663  		int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 4, 0);
   664 +		int ip = ptrace(PTRACE_PEEKUSER, proc->pid, off_ip, 0);
   665  
   666 -		*sysnum = insn & 0xFFFF;
   667 -		/* if it is a syscall, return 1 or 2 */
   668 -		if ((insn & 0xFFFF0000) == 0xef900000) {
   669 -			return ptrace(PTRACE_PEEKUSER, proc->pid, off_ip,
   670 -				      0) ? 2 : 1;
   671 +		if (insn == 0xef000000 || insn == 0x0f000000) {
   672 +			/* EABI syscall */
   673 +			*sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, off_r7, 0);
   674 +		} else if ((insn & 0xfff00000) == 0xef900000) {
   675 +			/* old ABI syscall */
   676 +			*sysnum = insn & 0xfffff;
   677 +		} else {
   678 +			/* TODO: handle swi<cond> variations */
   679 +			/* one possible reason for getting in here is that we
   680 +			 * are coming from a signal handler, so the current
   681 +			 * PC does not point to the instruction just after the
   682 +			 * "swi" one. */
   683 +			output_line(proc, "unexpected instruction 0x%x at %p", insn, pc - 4);
   684 +			return -1;
   685 +		}
   686 +		if ((*sysnum & 0xf0000) == 0xf0000) {
   687 +			/* arch-specific syscall */
   688 +			*sysnum &= ~0xf0000;
   689 +			return ip ? 4 : 3;
   690  		}
   691 +		/* ARM syscall convention: on syscall entry, ip is zero;
   692 +		 * on syscall exit, ip is non-zero */
   693 +		return ip ? 2 : 1;
   694  	}
   695  	return 0;
   696  }
   697  
   698  long gimme_arg(enum tof type, struct process *proc, int arg_num)
   699  {
   700 +	proc_archdep *a = (proc_archdep *) proc->arch_ptr;
   701 +
   702  	if (arg_num == -1) {	/* return value */
   703  		return ptrace(PTRACE_PEEKUSER, proc->pid, off_r0, 0);
   704  	}
   705 @@ -60,6 +89,10 @@
   706  	/* deal with the ARM calling conventions */
   707  	if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) {
   708  		if (arg_num < 4) {
   709 +			if (a->valid && type == LT_TOF_FUNCTION)
   710 +				return a->regs.uregs[arg_num];
   711 +			if (a->valid && type == LT_TOF_FUNCTIONR)
   712 +				return a->func_arg[arg_num];
   713  			return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * arg_num,
   714  				      0);
   715  		} else {
   716 @@ -69,6 +102,10 @@
   717  		}
   718  	} else if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) {
   719  		if (arg_num < 5) {
   720 +			if (a->valid && type == LT_TOF_SYSCALL)
   721 +				return a->regs.uregs[arg_num];
   722 +			if (a->valid && type == LT_TOF_SYSCALLR)
   723 +				return a->sysc_arg[arg_num];
   724  			return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * arg_num,
   725  				      0);
   726  		} else {
   727 @@ -86,4 +123,11 @@
   728  
   729  void save_register_args(enum tof type, struct process *proc)
   730  {
   731 +	proc_archdep *a = (proc_archdep *) proc->arch_ptr;
   732 +	if (a->valid) {
   733 +		if (type == LT_TOF_FUNCTION)
   734 +			memcpy(a->func_arg, a->regs.uregs, sizeof(a->func_arg));
   735 +		else
   736 +			memcpy(a->sysc_arg, a->regs.uregs, sizeof(a->sysc_arg));
   737 +	}
   738  }
   739 diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/ppc/arch.h ltrace-0.5/sysdeps/linux-gnu/ppc/arch.h
   740 --- ltrace-0.5.orig/sysdeps/linux-gnu/ppc/arch.h	2006-06-14 06:55:21.000000000 +0200
   741 +++ ltrace-0.5/sysdeps/linux-gnu/ppc/arch.h	2008-11-04 19:25:50.000000000 +0100
   742 @@ -4,9 +4,12 @@
   743  
   744  #define LT_ELFCLASS	ELFCLASS32
   745  #define LT_ELF_MACHINE	EM_PPC
   746 +
   747  #ifdef __powerpc64__ // Says 'ltrace' is 64 bits, says nothing about target.
   748  #define LT_ELFCLASS2	ELFCLASS64
   749  #define LT_ELF_MACHINE2	EM_PPC64
   750 +#define ARCH_SUPPORTS_OPD
   751 +#endif
   752  
   753  #define PLT_REINITALISATION_BP    "_start"
   754  
   755 @@ -16,6 +19,3 @@
   756  #if (PPC_NOP_LENGTH != BREAKPOINT_LENGTH)
   757  #error "Length of the breakpoint value not equal to the length of a nop instruction"
   758  #endif
   759 -
   760 -
   761 -#endif
   762 diff -durN ltrace-0.5.orig/testsuite/ltrace.minor/Makefile.in ltrace-0.5/testsuite/ltrace.minor/Makefile.in
   763 --- ltrace-0.5.orig/testsuite/ltrace.minor/Makefile.in	2006-03-14 00:12:01.000000000 +0100
   764 +++ ltrace-0.5/testsuite/ltrace.minor/Makefile.in	2008-11-04 19:25:50.000000000 +0100
   765 @@ -19,7 +19,7 @@
   766  
   767  .SUFFIXES:	
   768  clean:
   769 -	-rm -f demangle trace-fork trace-clone 
   770 +	-rm -f demangle trace-fork trace-clone trace-exec trace-exec1
   771  	-rm -f time-record-tt time-record-ttt time-record-T
   772  	-rm -f attach-process count-record
   773  	-rm -f print-instruction-pointer
   774 diff -durN ltrace-0.5.orig/testsuite/ltrace.minor/trace-clone.c ltrace-0.5/testsuite/ltrace.minor/trace-clone.c
   775 --- ltrace-0.5.orig/testsuite/ltrace.minor/trace-clone.c	2006-03-16 01:38:47.000000000 +0100
   776 +++ ltrace-0.5/testsuite/ltrace.minor/trace-clone.c	2008-11-04 19:25:50.000000000 +0100
   777 @@ -21,11 +21,11 @@
   778  int main ()
   779  {
   780    pid_t pid;
   781 -  static char stack[STACK_SIZE];
   782 +  char stack[STACK_SIZE];
   783  #ifdef __ia64__
   784    pid = __clone2((myfunc)&child, stack, STACK_SIZE, CLONE_FS, NULL);
   785  #else
   786 -  pid = clone((myfunc)&child, stack,CLONE_FS, NULL );
   787 +  pid = clone((myfunc)&child, stack + STACK_SIZE,CLONE_FS, NULL );
   788  #endif
   789    if (pid < 0)
   790      {
   791 diff -durN ltrace-0.5.orig/wait_for_something.c ltrace-0.5/wait_for_something.c
   792 --- ltrace-0.5.orig/wait_for_something.c	2006-02-20 22:48:07.000000000 +0100
   793 +++ ltrace-0.5/wait_for_something.c	2008-11-04 19:25:50.000000000 +0100
   794 @@ -71,6 +71,18 @@
   795  		event.thing = LT_EV_SYSRET;
   796  		event.e_un.sysnum = tmp;
   797  		return &event;
   798 +	case 3:
   799 +		event.thing = LT_EV_ARCH_SYSCALL;
   800 +		event.e_un.sysnum = tmp;
   801 +		return &event;
   802 +	case 4:
   803 +		event.thing = LT_EV_ARCH_SYSRET;
   804 +		event.e_un.sysnum = tmp;
   805 +		return &event;
   806 +	case -1:
   807 +		event.thing = LT_EV_NONE;
   808 +		continue_process(event.proc->pid);
   809 +		return &event;
   810  	}
   811  	if (WIFEXITED(status)) {
   812  		event.thing = LT_EV_EXIT;