diff options
author | Petr Machata <pmachata@redhat.com> | 2012-05-17 23:35:26 +0200 |
---|---|---|
committer | Petr Machata <pmachata@redhat.com> | 2012-08-29 19:03:17 +0200 |
commit | ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76 (patch) | |
tree | 7a0c25936e3eba577f52d0acb086e33d856fc674 | |
parent | 2d9be647dd7402402ad3d2d2f114632aba21eaca (diff) | |
download | ltrace-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.ac | 13 | ||||
-rw-r--r-- | ltrace-elf.c | 7 | ||||
-rw-r--r-- | sysdeps/linux-gnu/Makefile.am | 3 | ||||
-rw-r--r-- | sysdeps/linux-gnu/i386/Makefile.am | 16 | ||||
-rw-r--r-- | sysdeps/linux-gnu/i386/arch.h | 27 | ||||
-rw-r--r-- | sysdeps/linux-gnu/i386/plt.c | 16 | ||||
-rw-r--r-- | sysdeps/linux-gnu/i386/ptrace.h | 1 | ||||
-rw-r--r-- | sysdeps/linux-gnu/i386/regs.c | 40 | ||||
-rw-r--r-- | sysdeps/linux-gnu/i386/trace.c | 96 | ||||
-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.c | 116 | ||||
-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.c | 54 | ||||
-rw-r--r-- | sysdeps/linux-gnu/x86_64/signalent1.h | 1 | ||||
-rw-r--r-- | sysdeps/linux-gnu/x86_64/syscallent1.h | 1 |
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" |