This ports the m68k backend to ARCH_HAVE_FETCH_ARG, which fixes all
remaining testsuite failures.
---
 sysdeps/linux-gnu/m68k/Makefile.am |   3 +-
 sysdeps/linux-gnu/m68k/arch.h      |   2 +
 sysdeps/linux-gnu/m68k/fetch.c     | 240 +++++++++++++++++++++++++++++++++++++
 sysdeps/linux-gnu/m68k/trace.c     |  40 -------
 4 files changed, 244 insertions(+), 41 deletions(-)
 create mode 100644 sysdeps/linux-gnu/m68k/fetch.c

diff --git a/sysdeps/linux-gnu/m68k/Makefile.am 
b/sysdeps/linux-gnu/m68k/Makefile.am
index a79d2f7..766a9bb 100644
--- a/sysdeps/linux-gnu/m68k/Makefile.am
+++ b/sysdeps/linux-gnu/m68k/Makefile.am
@@ -4,7 +4,8 @@ noinst_LTLIBRARIES = \
 ___libcpu_la_SOURCES = \
        plt.c \
        regs.c \
-       trace.c
+       trace.c \
+       fetch.c
 
 noinst_HEADERS = \
        arch.h \
diff --git a/sysdeps/linux-gnu/m68k/arch.h b/sysdeps/linux-gnu/m68k/arch.h
index 9ca08ca..3829901 100644
--- a/sysdeps/linux-gnu/m68k/arch.h
+++ b/sysdeps/linux-gnu/m68k/arch.h
@@ -18,6 +18,8 @@
  * 02110-1301 USA
  */
 
+#define ARCH_HAVE_FETCH_ARG
+
 #define BREAKPOINT_VALUE { 0x4e, 0x4f }
 #define BREAKPOINT_LENGTH 2
 #define DECR_PC_AFTER_BREAK 2
diff --git a/sysdeps/linux-gnu/m68k/fetch.c b/sysdeps/linux-gnu/m68k/fetch.c
new file mode 100644
index 0000000..a92057b
--- /dev/null
+++ b/sysdeps/linux-gnu/m68k/fetch.c
@@ -0,0 +1,240 @@
+/*
+ * This file is part of ltrace.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/procfs.h>
+#include <sys/reg.h>
+
+#include "backend.h"
+#include "expr.h"
+#include "fetch.h"
+#include "proc.h"
+#include "ptrace.h"
+#include "type.h"
+#include "value.h"
+
+struct fetch_context
+{
+       elf_gregset_t regs;
+       elf_fpregset_t fpregs;
+
+       int arg_num;
+       arch_addr_t stack_pointer;
+       struct value retval;
+};
+
+static int
+fetch_register_banks(struct Process *proc, struct fetch_context *context,
+                    int floating)
+{
+       if (ptrace(PTRACE_GETREGS, proc->pid, 0, &context->regs) < 0)
+               return -1;
+
+       if (floating
+           && ptrace(PTRACE_GETFPREGS, proc->pid, 0, &context->fpregs) < 0)
+               return -1;
+
+       return 0;
+}
+
+struct fetch_context *
+arch_fetch_arg_init(enum tof type, struct Process *proc,
+                   struct arg_type_info *ret_info)
+{
+       struct fetch_context *context = malloc(sizeof(*context));
+       if (context == NULL)
+               return NULL;
+
+       assert(type != LT_TOF_FUNCTIONR && type != LT_TOF_SYSCALLR);
+       if (fetch_register_banks(proc, context, type == LT_TOF_FUNCTION) < 0) {
+       fail:
+               free(context);
+               return NULL;
+       }
+
+       context->arg_num = 0;
+       context->stack_pointer = (arch_addr_t)context->regs[PT_USP] + 4;
+
+       size_t sz = type_sizeof(proc, ret_info);
+       if (sz == (size_t)-1)
+               goto fail;
+
+       if (ret_info->type == ARGTYPE_STRUCT && !(sz <= 4 || sz == 8)) {
+               value_init(&context->retval, proc, NULL, ret_info, 0);
+
+               if (value_pass_by_reference(&context->retval) < 0)
+                       goto fail;
+               value_set_word(&context->retval, context->regs[PT_A1]);
+       } else {
+               value_init_detached(&context->retval, NULL, NULL, 0);
+       }
+
+       return context;
+}
+
+struct fetch_context *
+arch_fetch_arg_clone(struct Process *proc, struct fetch_context *context)
+{
+       struct fetch_context *ret = malloc(sizeof(*ret));
+       if (ret == NULL)
+               return NULL;
+       *ret = *context;
+       return ret;
+}
+
+int
+arch_fetch_arg_next(struct fetch_context *context, enum tof type,
+                   struct Process *proc, struct arg_type_info *info,
+                   struct value *valuep)
+{
+       size_t sz = type_sizeof(proc, info);
+       if (sz == (size_t)-1)
+               return -1;
+
+       if (type == LT_TOF_SYSCALL) {
+               int reg;
+
+               switch (context->arg_num++) {
+               case 0: reg = PT_D1; break;
+               case 1: reg = PT_D2; break;
+               case 2: reg = PT_D3; break;
+               case 3: reg = PT_D4; break;
+               case 4: reg = PT_D5; break;
+               case 5: reg = PT_A0; break;
+               default:
+                       assert(!"More than six syscall arguments???");
+                       abort();
+               }
+               value_set_word(valuep, context->regs[reg]);
+       } else {
+               size_t a = type_alignof(valuep->inferior, valuep->type);
+               if (a < 4)
+                       a = 4;
+               context->stack_pointer = (arch_addr_t)
+                       align((unsigned long)context->stack_pointer, a);
+               if (sz < 4)
+                       context->stack_pointer += 4 - sz;
+
+               valuep->where = VAL_LOC_INFERIOR;
+               valuep->u.address = context->stack_pointer;
+               context->stack_pointer += sz;
+       }
+
+       return 0;
+}
+
+int
+arch_fetch_retval(struct fetch_context *context, enum tof type,
+                 struct Process *proc, struct arg_type_info *info,
+                 struct value *valuep)
+{
+       if (fetch_register_banks(proc, context, type == LT_TOF_FUNCTIONR) < 0)
+               return -1;
+
+       if (context->retval.type != NULL) {
+               /* Struct return value was extracted when in fetch
+                * init.  */
+               *valuep = context->retval;
+               return 0;
+       }
+
+       size_t sz = type_sizeof(proc, info);
+       if (sz == (size_t)-1)
+               return -1;
+       if (value_reserve(valuep, sz) == NULL)
+               return -1;
+
+       switch (info->type) {
+       case ARGTYPE_VOID:
+               return 0;
+
+       case ARGTYPE_INT:
+       case ARGTYPE_UINT:
+       case ARGTYPE_LONG:
+       case ARGTYPE_ULONG:
+       case ARGTYPE_CHAR:
+       case ARGTYPE_SHORT:
+       case ARGTYPE_USHORT:
+       case ARGTYPE_POINTER:
+               {
+                       unsigned char *buf = value_get_raw_data(valuep);
+                       int reg = info->type == ARGTYPE_POINTER ? PT_A0 : PT_D0;
+                       unsigned char *val
+                               = (unsigned char *)&context->regs[reg];
+                       if (sz < 4) val += 4 - sz;
+                       memcpy(buf, val, sz);
+               }
+               return 0;
+
+       case ARGTYPE_FLOAT:
+       case ARGTYPE_DOUBLE:
+               {
+                       union {
+                               long double ld;
+                               double d;
+                               float f;
+                               char buf[0];
+                       } u;
+
+                       unsigned long *reg = &context->fpregs.fpregs[0];
+                       memcpy (&u.ld, reg, sizeof (u.ld));
+                       if (valuep->type->type == ARGTYPE_FLOAT)
+                               u.f = (float)u.ld;
+                       else if (valuep->type->type == ARGTYPE_DOUBLE)
+                               u.d = (double)u.ld;
+                       else {
+                               assert(!"Unexpected floating type!");
+                               abort();
+                       }
+                       unsigned char *buf = value_get_raw_data (valuep);
+                       memcpy (buf, u.buf, sz);
+               }
+               return 0;
+
+       case ARGTYPE_STRUCT:
+               {
+                       unsigned char *buf = value_get_raw_data(valuep);
+                       unsigned char *val
+                               = (unsigned char *)&context->regs[PT_D0];
+
+                       assert(sz <= 4 || sz == 8);
+                       if (sz < 4) val += 4 - sz;
+                       memcpy(buf, val, sz <= 4 ? sz : 4);
+                       if (sz == 8)
+                               memcpy(buf + 4, &context->regs[PT_D1], 4);
+               }
+               return 0;
+
+       case ARGTYPE_ARRAY:
+               assert(!"Unexpected m68k retval type!");
+               abort();
+       }
+
+       abort();
+}
+
+void
+arch_fetch_arg_done(struct fetch_context *context)
+{
+       if (context != NULL)
+               free(context);
+}
diff --git a/sysdeps/linux-gnu/m68k/trace.c b/sysdeps/linux-gnu/m68k/trace.c
index 4bec016..75b2a78 100644
--- a/sysdeps/linux-gnu/m68k/trace.c
+++ b/sysdeps/linux-gnu/m68k/trace.c
@@ -45,43 +45,3 @@ syscall_p(Process *proc, int status, int *sysnum) {
        }
        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 * PT_D0, 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 * PT_D1, 0);
-               case 1:
-                       return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_D2, 0);
-               case 2:
-                       return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_D3, 0);
-               case 3:
-                       return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_D4, 0);
-               case 4:
-                       return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_D5, 0);
-               default:
-                       fprintf(stderr,
-                               "gimme_arg called with wrong arguments\n");
-                       exit(2);
-               }
-#else
-               /* That hack works on m68k, too */
-               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;
-}
-- 
1.7.12


-- 
Andreas Schwab, [email protected]
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

_______________________________________________
Ltrace-devel mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/ltrace-devel

Reply via email to