[ltrace-commits] 01/01: Implement most of the parameter fetches for aarch64
Petr Machata
pmachata-guest at moszumanska.debian.org
Tue Jan 28 03:02:18 UTC 2014
This is an automated email from the git hooks/post-receive script.
pmachata-guest pushed a commit to branch pmachata/aarch64
in repository ltrace.
commit c71029b435e5421640e08608a65d2aa17fd65865
Author: Petr Machata <pmachata at apm-mustang-ev2-01.ml3.eng.bos.redhat.com>
Date: Mon Jan 27 22:00:17 2014 -0500
Implement most of the parameter fetches for aarch64
- There are still a couple failures, but most things pass now
---
sysdeps/linux-gnu/aarch64/fetch.c | 145 ++++++++++++++++++++++++++++++++------
1 file changed, 125 insertions(+), 20 deletions(-)
diff --git a/sysdeps/linux-gnu/aarch64/fetch.c b/sysdeps/linux-gnu/aarch64/fetch.c
index ef9cdc1..c57fe48 100644
--- a/sysdeps/linux-gnu/aarch64/fetch.c
+++ b/sysdeps/linux-gnu/aarch64/fetch.c
@@ -48,28 +48,15 @@ context_init(struct fetch_context *context, enum tof type, struct process *proc)
|| aarch64_read_fregs(proc, &context->fpregs) < 0)
return -1;
- /* XXX double cast */
context->ngrn = 0;
context->nsrn = 0;
+ /* XXX double cast */
context->nsaa = (arch_addr_t) (uintptr_t) context->gregs.sp;
return 0;
}
struct fetch_context *
-arch_fetch_arg_init(enum tof type, struct process *proc,
- struct arg_type_info *ret_info)
-{
- struct fetch_context *ret = malloc(sizeof *ret);
- if (ret == NULL || context_init(ret, type, proc) < 0) {
- free(ret);
- return NULL;
- }
-
- return ret;
-}
-
-struct fetch_context *
arch_fetch_arg_clone(struct process *proc, struct fetch_context *context)
{
struct fetch_context *ret = malloc(sizeof(*ret));
@@ -78,15 +65,81 @@ arch_fetch_arg_clone(struct process *proc, struct fetch_context *context)
return memcpy(ret, context, sizeof(*ret));
}
+static void
+fetch_next_gpr(struct fetch_context *context, unsigned char *buf)
+{
+ uint64_t u = context->gregs.regs[context->ngrn++];
+ memcpy(buf, &u, 8);
+}
+
static int
-copy_from(struct value *value, size_t sz, uint64_t u)
+fetch_gpr(struct fetch_context *context, struct value *value, size_t sz)
{
if (sz < 8)
sz = 8;
+
unsigned char *buf = value_reserve(value, sz);
if (buf == NULL)
return -1;
+
+ size_t i;
+ for (i = 0; i < sz; i += 8)
+ fetch_next_gpr(context, buf + i);
+
+ return 0;
+}
+
+static void
+fetch_next_sse(struct fetch_context *context, unsigned char *buf, size_t sz)
+{
+ __int128 u = context->fpregs.vregs[context->nsrn++];
memcpy(buf, &u, sz);
+}
+
+static int
+fetch_sse(struct fetch_context *context, struct value *value, size_t sz)
+{
+ unsigned char *buf = value_reserve(value, sz);
+ if (buf == NULL)
+ return -1;
+
+ fetch_next_sse(context, buf, sz);
+ return 0;
+}
+
+static int
+fetch_hfa(struct fetch_context *context,
+ struct value *value, struct arg_type_info *hfa_t, size_t count)
+{
+ size_t sz = type_sizeof(value->inferior, hfa_t);
+ unsigned char *buf = value_reserve(value, sz * count);
+ if (buf == NULL)
+ return -1;
+
+ size_t i;
+ for (i = 0; i < count; ++i) {
+ fetch_next_sse(context, buf, sz);
+ buf += sz;
+ }
+ return 0;
+}
+
+static int
+fetch_stack(struct fetch_context *context, struct value *value,
+ size_t align, size_t sz)
+{
+ unsigned char *buf = value_reserve(value, sz);
+ if (buf == NULL)
+ return -1;
+
+ /* XXX double casts */
+ uintptr_t sp = (uintptr_t) context->nsaa;
+ sp = ((sp + align - 1) / align) * align;
+ value_in_inferior(value, (arch_addr_t) sp);
+ if (sz < 8)
+ sz = 8;
+ sp += sz;
+ context->nsaa = (arch_addr_t) sp;
return 0;
}
@@ -103,6 +156,26 @@ pass_arg(struct fetch_context *context, enum tof type,
case ARGTYPE_VOID:
return 0;
+ case ARGTYPE_STRUCT:
+ case ARGTYPE_ARRAY:;
+ if (sz <= 16) {
+ size_t count;
+ struct arg_type_info *hfa_t
+ = type_get_hfa_type(info, &count);
+ if (hfa_t != NULL && context->nsrn + count <= 8)
+ return fetch_hfa(context, value, hfa_t, count);
+ }
+
+ if (sz <= 16) {
+ size_t count = sz / 8;
+ if (context->ngrn + count <= 8)
+ return fetch_gpr(context, value, sz);
+ }
+
+ if (value_pass_by_reference(value) < 0)
+ return -1;
+ sz = 8;
+
case ARGTYPE_INT:
case ARGTYPE_UINT:
case ARGTYPE_LONG:
@@ -112,18 +185,50 @@ pass_arg(struct fetch_context *context, enum tof type,
case ARGTYPE_USHORT:
case ARGTYPE_POINTER:
if (context->ngrn < 8 && sz <= 8)
- return copy_from(value, sz,
- context->gregs.regs[context->ngrn++]);
+ return fetch_gpr(context, value, sz);
+ /* We don't support types wider than 8 bytes as of
+ * now. */
+ assert(sz <= 8);
+
+ return fetch_stack(context, value,
+ type_alignof(proc, info), sz);
case ARGTYPE_FLOAT:
case ARGTYPE_DOUBLE:
- case ARGTYPE_ARRAY:
- case ARGTYPE_STRUCT:
- break;
+ if (context->nsrn < 8) {
+ /* ltrace doesn't support float128. */
+ assert(sz <= 8);
+ return fetch_sse(context, value, sz);
+ }
+
+ return fetch_stack(context, value,
+ type_alignof(proc, info), sz);
}
return -1;
}
+struct fetch_context *
+arch_fetch_arg_init(enum tof type, struct process *proc,
+ struct arg_type_info *ret_info)
+{
+ struct fetch_context *ret = malloc(sizeof *ret);
+ if (ret == NULL || context_init(ret, type, proc) < 0) {
+ fail:
+ free(ret);
+ return NULL;
+ }
+
+ struct fetch_context tmp = *ret;
+ struct value value;
+ value_init(&value, proc, NULL, ret_info, 0);
+ int rc = pass_arg(&tmp, type, proc, ret_info, &value);
+ value_destroy(&value);
+ if (rc < 0)
+ goto fail;
+
+ return ret;
+}
+
int
arch_fetch_arg_next(struct fetch_context *context, enum tof type,
struct process *proc, struct arg_type_info *info,
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/collab-maint/ltrace.git
More information about the ltrace-commits
mailing list