aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Machata <pmachata@redhat.com>2012-05-17 23:35:26 +0200
committerPetr Machata <pmachata@redhat.com>2012-08-29 19:03:17 +0200
commitddd96a3fbc7c54146d1d831810fc9e29c9bc3c76 (patch)
tree7a0c25936e3eba577f52d0acb086e33d856fc674
parent2d9be647dd7402402ad3d2d2f114632aba21eaca (diff)
downloadltrace-ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76.tar.gz
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.
-rw-r--r--configure.ac13
-rw-r--r--ltrace-elf.c7
-rw-r--r--sysdeps/linux-gnu/Makefile.am3
-rw-r--r--sysdeps/linux-gnu/i386/Makefile.am16
-rw-r--r--sysdeps/linux-gnu/i386/arch.h27
-rw-r--r--sysdeps/linux-gnu/i386/plt.c16
-rw-r--r--sysdeps/linux-gnu/i386/ptrace.h1
-rw-r--r--sysdeps/linux-gnu/i386/regs.c40
-rw-r--r--sysdeps/linux-gnu/i386/trace.c96
-rw-r--r--sysdeps/linux-gnu/x86/Makefile.am (renamed from sysdeps/linux-gnu/x86_64/Makefile.am)0
-rw-r--r--sysdeps/linux-gnu/x86/arch.h (renamed from sysdeps/linux-gnu/x86_64/arch.h)2
-rw-r--r--sysdeps/linux-gnu/x86/fetch.c (renamed from sysdeps/linux-gnu/x86_64/fetch.c)61
-rw-r--r--sysdeps/linux-gnu/x86/plt.c (renamed from sysdeps/linux-gnu/x86_64/plt.c)0
-rw-r--r--sysdeps/linux-gnu/x86/ptrace.h (renamed from sysdeps/linux-gnu/x86_64/ptrace.h)0
-rw-r--r--sysdeps/linux-gnu/x86/regs.c116
-rw-r--r--sysdeps/linux-gnu/x86/signalent.h (renamed from sysdeps/linux-gnu/x86_64/signalent.h)0
-rw-r--r--sysdeps/linux-gnu/x86/signalent1.h (renamed from sysdeps/linux-gnu/i386/signalent.h)0
-rw-r--r--sysdeps/linux-gnu/x86/syscallent.h (renamed from sysdeps/linux-gnu/i386/syscallent.h)1
-rw-r--r--sysdeps/linux-gnu/x86/syscallent1.h (renamed from sysdeps/linux-gnu/x86_64/syscallent.h)1
-rw-r--r--sysdeps/linux-gnu/x86/trace.c (renamed from sysdeps/linux-gnu/x86_64/trace.c)80
-rw-r--r--sysdeps/linux-gnu/x86_64/regs.c54
-rw-r--r--sysdeps/linux-gnu/x86_64/signalent1.h1
-rw-r--r--sysdeps/linux-gnu/x86_64/syscallent1.h1
23 files changed, 237 insertions, 299 deletions
diff --git a/configure.ac b/configure.ac
index a17e155..f651c9a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -18,10 +18,10 @@ AC_SUBST(HOST_OS)
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 @@ AC_CONFIG_FILES([
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 @@ open_elf(struct ltelf *lte, const char *filename)
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
index d5eb6e7..d5eb6e7 100644
--- a/sysdeps/linux-gnu/x86_64/Makefile.am
+++ b/sysdeps/linux-gnu/x86/Makefile.am
diff --git a/sysdeps/linux-gnu/x86_64/arch.h b/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
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 fetch_context
{
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 @@ struct fetch_context
} 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 @@ static void
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 @@ copy_sse_register(struct fetch_context *context, struct value *valuep,
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 @@ allocate_x87(struct fetch_context *context, struct value *valuep,
* 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 @@ allocate_integer(struct fetch_context *context, struct value *valuep,
switch (pool) {
case POOL_FUNCALL:
+#ifdef __x86_64__
switch (context->ireg) {
HANDLE(0, rdi);
HANDLE(1, rsi);
@@ -213,8 +233,12 @@ allocate_integer(struct fetch_context *context, struct value *valuep,
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 @@ allocate_integer(struct fetch_context *context, struct value *valuep,
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 @@ fetch_register_banks(struct Process *proc, struct fetch_context *context,
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 @@ arch_fetch_retval_32(struct fetch_context *context, enum tof type,
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 @@ arch_fetch_retval_32(struct fetch_context *context, enum tof type,
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 @@ arch_fetch_arg_init_64(struct fetch_context *ctx, enum tof type,
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
index bb1b2b1..bb1b2b1 100644
--- a/sysdeps/linux-gnu/x86_64/plt.c
+++ b/sysdeps/linux-gnu/x86/plt.c
diff --git a/sysdeps/linux-gnu/x86_64/ptrace.h b/sysdeps/linux-gnu/x86/ptrace.h
index e0f5261..e0f5261 100644
--- a/sysdeps/linux-gnu/x86_64/ptrace.h
+++ b/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
index d58a36c..d58a36c 100644
--- a/sysdeps/linux-gnu/x86_64/signalent.h
+++ b/sysdeps/linux-gnu/x86/signalent.h
diff --git a/sysdeps/linux-gnu/i386/signalent.h b/sysdeps/linux-gnu/x86/signalent1.h
index 5395f82..5395f82 100644
--- a/sysdeps/linux-gnu/i386/signalent.h
+++ b/sysdeps/linux-gnu/x86/signalent1.h
diff --git a/sysdeps/linux-gnu/i386/syscallent.h b/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
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
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 @@ syscall_p(struct Process *proc, int status, int *sysnum)
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,53 @@ syscall_p(struct Process *proc, int status, int *sysnum)
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:
+ return 0;
+
case ARGTYPE_CHAR:
+ return 1;
+
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;
+ return 2;
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 || proc->e_machine != EM_386)
+ if (proc == NULL)
return (size_t)-2;
switch (info->type) {
- case ARGTYPE_ARRAY:
- case ARGTYPE_STRUCT:
- /* Use default value. */
- return (size_t)-2;
+ case ARGTYPE_VOID:
+ assert(info->type != ARGTYPE_VOID);
+ break;
case ARGTYPE_CHAR:
return 1;
@@ -140,18 +166,24 @@ arch_type_alignof(struct Process *proc, struct arg_type_info *info)
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 proc->e_machine == EM_X86_64 ? 8 : 4;
- case ARGTYPE_VOID:
- assert(!"Unexpected i386 alignof type!");
- abort();
+ 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"