[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