Merge i386 and x86_64 back ends into a general x86

The reason being that x86_64 needs to handle i386 anyway, and keeping the
two together might reduce code duplicity.
diff --git a/configure.ac b/configure.ac
index a17e155..f651c9a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -18,10 +18,10 @@
 
 case "${host_cpu}" in
     arm*|sa110)		HOST_CPU="arm" ;;
-    i?86)		HOST_CPU="i386" ;;
     powerpc|powerpc64)	HOST_CPU="ppc" ;;
     sun4u|sparc64)	HOST_CPU="sparc" ;;
     s390x)		HOST_CPU="s390" ;;
+    i?86|x86_64)	HOST_CPU="x86" ;;
     *)			HOST_CPU="${host_cpu}" ;;
 esac
 AC_SUBST(HOST_CPU)
@@ -267,16 +267,7 @@
 	Makefile
 	sysdeps/Makefile
 	sysdeps/linux-gnu/Makefile
-	sysdeps/linux-gnu/alpha/Makefile
-	sysdeps/linux-gnu/arm/Makefile
-	sysdeps/linux-gnu/i386/Makefile
-	sysdeps/linux-gnu/ia64/Makefile
-	sysdeps/linux-gnu/m68k/Makefile
-	sysdeps/linux-gnu/mipsel/Makefile
-	sysdeps/linux-gnu/ppc/Makefile
-	sysdeps/linux-gnu/s390/Makefile
-	sysdeps/linux-gnu/sparc/Makefile
-	sysdeps/linux-gnu/x86_64/Makefile
+	sysdeps/linux-gnu/${HOST_CPU}/Makefile
 	testsuite/Makefile
 	testsuite/ltrace.main/Makefile
 	testsuite/ltrace.minor/Makefile
diff --git a/ltrace-elf.c b/ltrace-elf.c
index 9b6cf6b..99d06d6 100644
--- a/ltrace-elf.c
+++ b/ltrace-elf.c
@@ -273,8 +273,11 @@
 		exit(EXIT_FAILURE);
 	}
 
-	if ((lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS
-	     || lte->ehdr.e_machine != LT_ELF_MACHINE)
+	if (1
+#ifdef LT_ELF_MACHINE
+	    && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS
+		|| lte->ehdr.e_machine != LT_ELF_MACHINE)
+#endif
 #ifdef LT_ELF_MACHINE2
 	    && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS2
 		|| lte->ehdr.e_machine != LT_ELF_MACHINE2)
diff --git a/sysdeps/linux-gnu/Makefile.am b/sysdeps/linux-gnu/Makefile.am
index e385ea7..80e6594 100644
--- a/sysdeps/linux-gnu/Makefile.am
+++ b/sysdeps/linux-gnu/Makefile.am
@@ -1,14 +1,13 @@
 DIST_SUBDIRS = \
 	alpha \
 	arm \
-	i386 \
 	ia64 \
 	m68k \
 	mipsel \
 	ppc \
 	s390 \
 	sparc \
-	x86_64
+	x86
 
 SUBDIRS = \
 	$(HOST_CPU)
diff --git a/sysdeps/linux-gnu/i386/Makefile.am b/sysdeps/linux-gnu/i386/Makefile.am
deleted file mode 100644
index a79d2f7..0000000
--- a/sysdeps/linux-gnu/i386/Makefile.am
+++ /dev/null
@@ -1,16 +0,0 @@
-noinst_LTLIBRARIES = \
-	../libcpu.la
-
-___libcpu_la_SOURCES = \
-	plt.c \
-	regs.c \
-	trace.c
-
-noinst_HEADERS = \
-	arch.h \
-	ptrace.h \
-	signalent.h \
-	syscallent.h
-
-MAINTAINERCLEANFILES = \
-	Makefile.in
diff --git a/sysdeps/linux-gnu/i386/arch.h b/sysdeps/linux-gnu/i386/arch.h
deleted file mode 100644
index 4bb80a4..0000000
--- a/sysdeps/linux-gnu/i386/arch.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * This file is part of ltrace.
- * Copyright (C) 1998,2004 Juan Cespedes
- *
- * 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
- */
-
-#define BREAKPOINT_VALUE {0xcc}
-#define BREAKPOINT_LENGTH 1
-#define DECR_PC_AFTER_BREAK 1
-#define ARCH_ENDIAN_LITTLE
-
-#define LT_ELFCLASS	ELFCLASS32
-#define LT_ELF_MACHINE	EM_386
diff --git a/sysdeps/linux-gnu/i386/plt.c b/sysdeps/linux-gnu/i386/plt.c
deleted file mode 100644
index daaf15a..0000000
--- a/sysdeps/linux-gnu/i386/plt.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <gelf.h>
-#include "proc.h"
-#include "library.h"
-#include "ltrace-elf.h"
-
-GElf_Addr
-arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela)
-{
-	return lte->plt_addr + (ndx + 1) * 16;
-}
-
-void *
-sym2addr(struct Process *proc, struct library_symbol *sym)
-{
-	return sym->enter_addr;
-}
diff --git a/sysdeps/linux-gnu/i386/ptrace.h b/sysdeps/linux-gnu/i386/ptrace.h
deleted file mode 100644
index c3cbcb6..0000000
--- a/sysdeps/linux-gnu/i386/ptrace.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <sys/ptrace.h>
diff --git a/sysdeps/linux-gnu/i386/regs.c b/sysdeps/linux-gnu/i386/regs.c
deleted file mode 100644
index a1584ac..0000000
--- a/sysdeps/linux-gnu/i386/regs.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "config.h"
-
-#include <sys/types.h>
-#include <sys/ptrace.h>
-#include <asm/ptrace.h>
-
-#include "proc.h"
-
-#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
-# define PTRACE_PEEKUSER PTRACE_PEEKUSR
-#endif
-
-#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
-# define PTRACE_POKEUSER PTRACE_POKEUSR
-#endif
-
-void *
-get_instruction_pointer(Process *proc) {
-	return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4 * EIP, 0);
-}
-
-void
-set_instruction_pointer(Process *proc, void *addr) {
-	ptrace(PTRACE_POKEUSER, proc->pid, 4 * EIP, (long)addr);
-}
-
-void *
-get_stack_pointer(Process *proc) {
-	return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4 * UESP, 0);
-}
-
-void *
-get_return_addr(Process *proc, void *stack_pointer) {
-	return (void *)ptrace(PTRACE_PEEKTEXT, proc->pid, stack_pointer, 0);
-}
-
-void
-set_return_addr(Process *proc, void *addr) {
-	ptrace(PTRACE_POKETEXT, proc->pid, proc->stack_pointer, (long)addr);
-}
diff --git a/sysdeps/linux-gnu/i386/trace.c b/sysdeps/linux-gnu/i386/trace.c
deleted file mode 100644
index e58811f..0000000
--- a/sysdeps/linux-gnu/i386/trace.c
+++ /dev/null
@@ -1,96 +0,0 @@
-#include "config.h"
-
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <asm/ptrace.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdlib.h>
-
-#include "proc.h"
-#include "common.h"
-
-#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
-# define PTRACE_PEEKUSER PTRACE_PEEKUSR
-#endif
-
-#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
-# define PTRACE_POKEUSER PTRACE_POKEUSR
-#endif
-
-void
-get_arch_dep(Process *proc) {
-}
-
-/* Returns 1 if syscall, 2 if sysret, 0 otherwise.
- */
-int
-syscall_p(struct Process *proc, int status, int *sysnum)
-{
-	if (WIFSTOPPED(status)
-	    && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
-		struct callstack_element *elem = NULL;
-		if (proc->callstack_depth > 0)
-			elem = proc->callstack + proc->callstack_depth - 1;
-
-		*sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, 4 * ORIG_EAX, 0);
-		if (*sysnum == -1) {
-			if (errno)
-				return -1;
-			/* Otherwise, ORIG_EAX == -1 means that the
-			 * system call should not be restarted.  In
-			 * that case rely on what we have on
-			 * stack.  */
-			if (elem != NULL && elem->is_syscall)
-				*sysnum = elem->c_un.syscall;
-		}
-
-		if (elem != NULL && elem->is_syscall
-		    && elem->c_un.syscall == *sysnum)
-			return 2;
-
-		if (*sysnum >= 0)
-			return 1;
-	}
-	return 0;
-}
-
-long
-gimme_arg(enum tof type, Process *proc, int arg_num, struct arg_type_info *info)
-{
-	if (arg_num == -1) {	/* return value */
-		return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * EAX, 0);
-	}
-
-	if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) {
-		return ptrace(PTRACE_PEEKTEXT, proc->pid,
-			      proc->stack_pointer + 4 * (arg_num + 1), 0);
-	} else if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) {
-#if 0
-		switch (arg_num) {
-		case 0:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * EBX, 0);
-		case 1:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * ECX, 0);
-		case 2:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * EDX, 0);
-		case 3:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * ESI, 0);
-		case 4:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * EDI, 0);
-		default:
-			fprintf(stderr,
-				"gimme_arg called with wrong arguments\n");
-			exit(2);
-		}
-#else
-		return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * arg_num, 0);
-#endif
-	} else {
-		fprintf(stderr, "gimme_arg called with wrong arguments\n");
-		exit(1);
-	}
-
-	return 0;
-}
diff --git a/sysdeps/linux-gnu/x86_64/Makefile.am b/sysdeps/linux-gnu/x86/Makefile.am
similarity index 100%
rename from sysdeps/linux-gnu/x86_64/Makefile.am
rename to sysdeps/linux-gnu/x86/Makefile.am
diff --git a/sysdeps/linux-gnu/x86_64/arch.h b/sysdeps/linux-gnu/x86/arch.h
similarity index 97%
rename from sysdeps/linux-gnu/x86_64/arch.h
rename to sysdeps/linux-gnu/x86/arch.h
index 5c41f3d..77a09d7 100644
--- a/sysdeps/linux-gnu/x86_64/arch.h
+++ b/sysdeps/linux-gnu/x86/arch.h
@@ -28,8 +28,10 @@
 #define ARCH_HAVE_ALIGNOF
 #define ARCH_ENDIAN_LITTLE
 
+#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
 
diff --git a/sysdeps/linux-gnu/x86_64/fetch.c b/sysdeps/linux-gnu/x86/fetch.c
similarity index 94%
rename from sysdeps/linux-gnu/x86_64/fetch.c
rename to sysdeps/linux-gnu/x86/fetch.c
index 4df97c0..d9364ae 100644
--- a/sysdeps/linux-gnu/x86_64/fetch.c
+++ b/sysdeps/linux-gnu/x86/fetch.c
@@ -28,6 +28,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "backend.h"
 #include "expr.h"
 #include "fetch.h"
 #include "proc.h"
@@ -55,6 +56,7 @@
 {
 	struct user_regs_struct iregs;
 	struct user_fpregs_struct fpregs;
+
 	void *stack_pointer;
 	size_t ireg;	/* Used-up integer registers.  */
 	size_t freg;	/* Used-up floating registers.  */
@@ -69,10 +71,18 @@
 		} x86_64;
 		struct {
 			struct value retval;
-		} i386;
+		} ix86;
 	} u;
 };
 
+#ifndef __x86_64__
+__attribute__((noreturn)) static void
+i386_unreachable(void)
+{
+	abort();
+}
+#endif
+
 static int
 contains_unaligned_fields(struct arg_type_info *info)
 {
@@ -104,6 +114,7 @@
 copy_sse_register(struct fetch_context *context, struct value *valuep,
 		  int half, size_t sz, size_t offset)
 {
+#ifdef __x86_64__
 	union {
 		uint32_t sse[4];
 		long halves[2];
@@ -115,6 +126,9 @@
 		unsigned char *buf = value_get_raw_data(valuep);
 		memcpy(buf + offset, u.halves + half, sz);
 	}
+#else
+	i386_unreachable();
+#endif
 }
 
 static void
@@ -175,7 +189,12 @@
 		 * value_set_type), but for that we first need to
 		 * support long double in the first place.  */
 
-		unsigned int *reg = &context->fpregs.st_space[0];
+#ifdef __x86_64__
+		unsigned int *reg;
+#else
+		long int *reg;
+#endif
+		reg = &context->fpregs.st_space[0];
 		memcpy(&u.ld, reg, sizeof(u));
 		if (valuep->type->type == ARGTYPE_FLOAT)
 			u.f = (float)u.ld;
@@ -202,6 +221,7 @@
 
 	switch (pool) {
 	case POOL_FUNCALL:
+#ifdef __x86_64__
 		switch (context->ireg) {
 			HANDLE(0, rdi);
 			HANDLE(1, rsi);
@@ -213,8 +233,12 @@
 			allocate_stack_slot(context, valuep, sz, offset, 8);
 			return CLASS_MEMORY;
 		}
+#else
+		i386_unreachable();
+#endif
 
 	case POOL_SYSCALL:
+#ifdef __x86_64__
 		switch (context->ireg) {
 			HANDLE(0, rdi);
 			HANDLE(1, rsi);
@@ -226,13 +250,20 @@
 			assert(!"More than six syscall arguments???");
 			abort();
 		}
+#else
+		i386_unreachable();
+#endif
 
 	case POOL_RETVAL:
 		switch (context->ireg) {
+#ifdef __x86_64__
 			HANDLE(0, rax);
 			HANDLE(1, rdx);
+#else
+			HANDLE(0, eax);
+#endif
 		default:
-			assert(!"More than two return value classes???");
+			assert(!"Too many return value classes.");
 			abort();
 		}
 	}
@@ -482,9 +513,11 @@
 	context->ireg = 0;
 
 	if (floating) {
+#ifdef __x86_64__
 		if (ptrace(PTRACE_GETFPREGS, proc->pid,
 			   0, &context->fpregs) < 0)
 			return -1;
+#endif
 		context->freg = 0;
 	} else {
 		context->freg = -1;
@@ -515,11 +548,11 @@
 	if (fetch_register_banks(proc, context, type == LT_TOF_FUNCTIONR) < 0)
 		return -1;
 
-	struct value *retval = &context->u.i386.retval;
+	struct value *retval = &context->u.ix86.retval;
 	if (retval->type != NULL) {
 		/* Struct return value was extracted when in fetch
 		 * init.  */
-		memcpy(valuep, &context->u.i386.retval, sizeof(*valuep));
+		memcpy(valuep, &context->u.ix86.retval, sizeof(*valuep));
 		return 0;
 	}
 
@@ -561,18 +594,30 @@
 	abort();
 }
 
+static target_address_t
+fetch_stack_pointer(struct fetch_context *context)
+{
+	target_address_t sp;
+#ifdef __x86_64__
+	sp = (target_address_t)context->iregs.rsp;
+#else
+	sp = (target_address_t)context->iregs.esp;
+#endif
+	return sp;
+}
+
 struct fetch_context *
 arch_fetch_arg_init_32(struct fetch_context *context,
 		       enum tof type, struct Process *proc,
 		       struct arg_type_info *ret_info)
 {
-	context->stack_pointer = (void *)(context->iregs.rsp + 4);
+	context->stack_pointer = fetch_stack_pointer(context) + 4;
 
 	size_t sz = type_sizeof(proc, ret_info);
 	if (sz == (size_t)-1)
 		return NULL;
 
-	struct value *retval = &context->u.i386.retval;
+	struct value *retval = &context->u.ix86.retval;
 	if (ret_info->type == ARGTYPE_STRUCT) {
 		value_init(retval, proc, NULL, ret_info, 0);
 
@@ -593,7 +638,7 @@
 		       struct Process *proc, struct arg_type_info *ret_info)
 {
 	/* The first stack slot holds a return address.  */
-	ctx->stack_pointer = (void *)(ctx->iregs.rsp + 8);
+	ctx->stack_pointer = fetch_stack_pointer(ctx) + 8;
 
 	size_t size;
 	ctx->u.x86_64.num_ret_classes
diff --git a/sysdeps/linux-gnu/x86_64/plt.c b/sysdeps/linux-gnu/x86/plt.c
similarity index 100%
rename from sysdeps/linux-gnu/x86_64/plt.c
rename to sysdeps/linux-gnu/x86/plt.c
diff --git a/sysdeps/linux-gnu/x86_64/ptrace.h b/sysdeps/linux-gnu/x86/ptrace.h
similarity index 100%
rename from sysdeps/linux-gnu/x86_64/ptrace.h
rename to sysdeps/linux-gnu/x86/ptrace.h
diff --git a/sysdeps/linux-gnu/x86/regs.c b/sysdeps/linux-gnu/x86/regs.c
new file mode 100644
index 0000000..477abca
--- /dev/null
+++ b/sysdeps/linux-gnu/x86/regs.c
@@ -0,0 +1,116 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 1998,2002,2004,2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <sys/reg.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "backend.h"
+#include "proc.h"
+
+#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
+# define PTRACE_PEEKUSER PTRACE_PEEKUSR
+#endif
+
+#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
+# define PTRACE_POKEUSER PTRACE_POKEUSR
+#endif
+
+#ifdef __x86_64__
+# define XIP (8 * RIP)
+# define XSP (8 * RSP)
+#else
+# define XIP (4 * EIP)
+# define XSP (4 * UESP)
+#endif
+
+static target_address_t
+conv_32(target_address_t val)
+{
+	/* XXX Drop the multiple double casts when target_address_t
+	 * becomes integral.  */
+	return (target_address_t)(uintptr_t)(uint32_t)(uintptr_t)val;
+}
+
+void *
+get_instruction_pointer(struct Process *proc)
+{
+	long int ret = ptrace(PTRACE_PEEKUSER, proc->pid, XIP, 0);
+	if (proc->e_machine == EM_386)
+		ret &= 0xffffffff;
+	return (void *)ret;
+}
+
+void
+set_instruction_pointer(struct Process *proc, target_address_t addr)
+{
+	if (proc->e_machine == EM_386)
+		addr = conv_32(addr);
+	ptrace(PTRACE_POKEUSER, proc->pid, XIP, addr);
+}
+
+void *
+get_stack_pointer(struct Process *proc)
+{
+	long sp = ptrace(PTRACE_PEEKUSER, proc->pid, XSP, 0);
+	if (sp == -1 && errno) {
+		fprintf(stderr, "Couldn't read SP register: %s\n",
+			strerror(errno));
+		return NULL;
+	}
+
+	/* XXX Drop the multiple double casts when target_address_t
+	 * becomes integral.  */
+	target_address_t ret = (target_address_t)(uintptr_t)sp;
+	if (proc->e_machine == EM_386)
+		ret = conv_32(ret);
+	return ret;
+}
+
+void *
+get_return_addr(struct Process *proc, void *sp)
+{
+	long a = ptrace(PTRACE_PEEKTEXT, proc->pid, sp, 0);
+	if (a == -1 && errno) {
+		fprintf(stderr, "Couldn't read return value: %s\n",
+			strerror(errno));
+		return NULL;
+	}
+
+	/* XXX Drop the multiple double casts when target_address_t
+	 * becomes integral.  */
+	target_address_t ret = (target_address_t)(uintptr_t)a;
+	if (proc->e_machine == EM_386)
+		ret = conv_32(ret);
+	return ret;
+}
+
+void
+set_return_addr(Process *proc, void *addr) {
+	if (proc->e_machine == EM_386)
+		addr = (void *)((long int)addr & 0xffffffff);
+	ptrace(PTRACE_POKETEXT, proc->pid, proc->stack_pointer, addr);
+}
diff --git a/sysdeps/linux-gnu/x86_64/signalent.h b/sysdeps/linux-gnu/x86/signalent.h
similarity index 100%
rename from sysdeps/linux-gnu/x86_64/signalent.h
rename to sysdeps/linux-gnu/x86/signalent.h
diff --git a/sysdeps/linux-gnu/i386/signalent.h b/sysdeps/linux-gnu/x86/signalent1.h
similarity index 100%
rename from sysdeps/linux-gnu/i386/signalent.h
rename to sysdeps/linux-gnu/x86/signalent1.h
diff --git a/sysdeps/linux-gnu/i386/syscallent.h b/sysdeps/linux-gnu/x86/syscallent.h
similarity index 99%
rename from sysdeps/linux-gnu/i386/syscallent.h
rename to sysdeps/linux-gnu/x86/syscallent.h
index 8f4c887..b3883c5 100644
--- a/sysdeps/linux-gnu/i386/syscallent.h
+++ b/sysdeps/linux-gnu/x86/syscallent.h
@@ -1,3 +1,4 @@
+/* This file is for i386 system call names.  */
 	"restart_syscall",                 /* 0 */
 	"exit",                            /* 1 */
 	"fork",                            /* 2 */
diff --git a/sysdeps/linux-gnu/x86_64/syscallent.h b/sysdeps/linux-gnu/x86/syscallent1.h
similarity index 98%
rename from sysdeps/linux-gnu/x86_64/syscallent.h
rename to sysdeps/linux-gnu/x86/syscallent1.h
index 5e5f88a..1629816 100644
--- a/sysdeps/linux-gnu/x86_64/syscallent.h
+++ b/sysdeps/linux-gnu/x86/syscallent1.h
@@ -1,3 +1,4 @@
+/* This file is for x86_64 system call names.  */
 "read",				/* 0 */
     "write",			/* 1 */
     "open",			/* 2 */
diff --git a/sysdeps/linux-gnu/x86_64/trace.c b/sysdeps/linux-gnu/x86/trace.c
similarity index 78%
rename from sysdeps/linux-gnu/x86_64/trace.c
rename to sysdeps/linux-gnu/x86/trace.c
index 9b32196..cc1a6a1 100644
--- a/sysdeps/linux-gnu/x86_64/trace.c
+++ b/sysdeps/linux-gnu/x86/trace.c
@@ -1,6 +1,6 @@
 /*
  * This file is part of ltrace.
- * Copyright (C) 2010,2011,2012 Petr Machata
+ * Copyright (C) 2010,2011,2012 Petr Machata, Red Hat Inc.
  * Copyright (C) 2004,2008,2009 Juan Cespedes
  * Copyright (C) 2006 Ian Wienand
  *
@@ -23,6 +23,7 @@
 #include "config.h"
 
 #include <sys/reg.h>
+#include <sys/wait.h>
 #include <assert.h>
 #include <errno.h>
 #include <stdlib.h>
@@ -41,16 +42,30 @@
 # define PTRACE_POKEUSER PTRACE_POKEUSR
 #endif
 
+#ifdef __x86_64__
+# define ORIG_XAX (8 * ORIG_RAX)
+#else
+# define ORIG_XAX (4 * ORIG_EAX)
+#endif
+
+#ifdef __x86_64__
+static const int x86_64 = 1;
+#else
+static const int x86_64 = 0;
+#endif
+
 void
 get_arch_dep(struct Process *proc)
 {
-	long l = ptrace(PTRACE_PEEKUSER, proc->pid, 8 * CS, 0);
-	if (l == -1 && errno != 0)
-		return;
+	/* Unfortunately there are still remnants of mask_32bit uses
+	 * around.  */
 
-	if (l == 0x23) {
-		proc->mask_32bit = 1;
+	if (proc->e_machine == EM_X86_64) {
+		proc->mask_32bit = 0;
 		proc->personality = 1;
+	} else if (x86_64) { /* x86_64/i386 */
+		proc->mask_32bit = 1;
+		proc->personality = 0;
 	} else {
 		proc->mask_32bit = 0;
 		proc->personality = 0;
@@ -68,7 +83,7 @@
 		if (proc->callstack_depth > 0)
 			elem = proc->callstack + proc->callstack_depth - 1;
 
-		long int ret = ptrace(PTRACE_PEEKUSER, proc->pid, 8 * ORIG_RAX, 0);
+		long int ret = ptrace(PTRACE_PEEKUSER, proc->pid, ORIG_XAX, 0);
 		if (ret == -1) {
 			if (errno)
 				return -1;
@@ -96,42 +111,12 @@
 size_t
 arch_type_sizeof(struct Process *proc, struct arg_type_info *info)
 {
-	if (proc == NULL || proc->e_machine != EM_386)
+	if (proc == NULL)
 		return (size_t)-2;
 
 	switch (info->type) {
 	case ARGTYPE_VOID:
-	case ARGTYPE_CHAR:
-	case ARGTYPE_SHORT:
-	case ARGTYPE_USHORT:
-	case ARGTYPE_FLOAT:
-	case ARGTYPE_DOUBLE:
-	case ARGTYPE_ARRAY:
-	case ARGTYPE_STRUCT:
-		/* Use default value.  */
-		return (size_t)-2;
-
-	case ARGTYPE_INT:
-	case ARGTYPE_UINT:
-	case ARGTYPE_LONG:
-	case ARGTYPE_ULONG:
-	case ARGTYPE_POINTER:
-		return 4;
-	}
-	abort();
-}
-
-size_t
-arch_type_alignof(struct Process *proc, struct arg_type_info *info)
-{
-	if (proc == NULL || proc->e_machine != EM_386)
-		return (size_t)-2;
-
-	switch (info->type) {
-	case ARGTYPE_ARRAY:
-	case ARGTYPE_STRUCT:
-		/* Use default value.  */
-		return (size_t)-2;
+		return 0;
 
 	case ARGTYPE_CHAR:
 		return 1;
@@ -140,18 +125,65 @@
 	case ARGTYPE_USHORT:
 		return 2;
 
-	case ARGTYPE_FLOAT:
-	case ARGTYPE_DOUBLE:
 	case ARGTYPE_INT:
 	case ARGTYPE_UINT:
+		return 4;
+
 	case ARGTYPE_LONG:
 	case ARGTYPE_ULONG:
 	case ARGTYPE_POINTER:
+		return proc->e_machine == EM_X86_64 ? 8 : 4;
+
+	case ARGTYPE_FLOAT:
+		return 4;
+	case ARGTYPE_DOUBLE:
+		return 8;
+
+	case ARGTYPE_ARRAY:
+	case ARGTYPE_STRUCT:
+		/* Use default value.  */
+		return (size_t)-2;
+	}
+	assert(info->type != info->type);
+	abort();
+}
+
+size_t
+arch_type_alignof(struct Process *proc, struct arg_type_info *info)
+{
+	if (proc == NULL)
+		return (size_t)-2;
+
+	switch (info->type) {
+	case ARGTYPE_VOID:
+		assert(info->type != ARGTYPE_VOID);
+		break;
+
+	case ARGTYPE_CHAR:
+		return 1;
+
+	case ARGTYPE_SHORT:
+	case ARGTYPE_USHORT:
+		return 2;
+
+	case ARGTYPE_INT:
+	case ARGTYPE_UINT:
 		return 4;
 
-	case ARGTYPE_VOID:
-		assert(!"Unexpected i386 alignof type!");
-		abort();
+	case ARGTYPE_LONG:
+	case ARGTYPE_ULONG:
+	case ARGTYPE_POINTER:
+		return proc->e_machine == EM_X86_64 ? 8 : 4;
+
+	case ARGTYPE_FLOAT:
+		return 4;
+	case ARGTYPE_DOUBLE:
+		return proc->e_machine == EM_X86_64 ? 8 : 4;
+
+	case ARGTYPE_ARRAY:
+	case ARGTYPE_STRUCT:
+		/* Use default value.  */
+		return (size_t)-2;
 	}
 	abort();
 }
diff --git a/sysdeps/linux-gnu/x86_64/regs.c b/sysdeps/linux-gnu/x86_64/regs.c
deleted file mode 100644
index 0ff3281..0000000
--- a/sysdeps/linux-gnu/x86_64/regs.c
+++ /dev/null
@@ -1,54 +0,0 @@
-#include "config.h"
-
-#include <sys/types.h>
-#include <sys/ptrace.h>
-#include <sys/reg.h>
-
-#include "proc.h"
-
-#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
-# define PTRACE_PEEKUSER PTRACE_PEEKUSR
-#endif
-
-#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
-# define PTRACE_POKEUSER PTRACE_POKEUSR
-#endif
-
-void *
-get_instruction_pointer(Process *proc) {
-	long int ret = ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RIP, 0);
-	if (proc->mask_32bit)
-		ret &= 0xffffffff;
-	return (void *)ret;
-}
-
-void
-set_instruction_pointer(Process *proc, void *addr) {
-	if (proc->mask_32bit)
-		addr = (void *)((long int)addr & 0xffffffff);
-	ptrace(PTRACE_POKEUSER, proc->pid, 8 * RIP, addr);
-}
-
-void *
-get_stack_pointer(Process *proc) {
-	long int ret = ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RSP, 0);
-	if (proc->mask_32bit)
-		ret &= 0xffffffff;
-	return (void *)ret;
-}
-
-void *
-get_return_addr(Process *proc, void *stack_pointer) {
-	unsigned long int ret;
-	ret = ptrace(PTRACE_PEEKTEXT, proc->pid, stack_pointer, 0);
-	if (proc->mask_32bit)
-		ret &= 0xffffffff;
-	return (void *)ret;
-}
-
-void
-set_return_addr(Process *proc, void *addr) {
-	if (proc->mask_32bit)
-		addr = (void *)((long int)addr & 0xffffffff);
-	ptrace(PTRACE_POKETEXT, proc->pid, proc->stack_pointer, addr);
-}
diff --git a/sysdeps/linux-gnu/x86_64/signalent1.h b/sysdeps/linux-gnu/x86_64/signalent1.h
deleted file mode 100644
index 5ead946..0000000
--- a/sysdeps/linux-gnu/x86_64/signalent1.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "i386/signalent.h"
diff --git a/sysdeps/linux-gnu/x86_64/syscallent1.h b/sysdeps/linux-gnu/x86_64/syscallent1.h
deleted file mode 100644
index d8dd9f7..0000000
--- a/sysdeps/linux-gnu/x86_64/syscallent1.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "i386/syscallent.h"