|
|
f84355 |
diff --git a/sysdeps/linux-gnu/ppc/arch.h b/sysdeps/linux-gnu/ppc/arch.h
|
|
|
f84355 |
index d5ad759..a8b67bb 100644
|
|
|
f84355 |
--- a/sysdeps/linux-gnu/ppc/arch.h
|
|
|
f84355 |
+++ b/sysdeps/linux-gnu/ppc/arch.h
|
|
|
f84355 |
@@ -32,36 +32,45 @@
|
|
|
f84355 |
#define LT_ELF_MACHINE EM_PPC
|
|
|
f84355 |
|
|
|
f84355 |
#ifdef __powerpc64__ // Says 'ltrace' is 64 bits, says nothing about target.
|
|
|
f84355 |
-#define LT_ELFCLASS2 ELFCLASS64
|
|
|
f84355 |
-#define LT_ELF_MACHINE2 EM_PPC64
|
|
|
f84355 |
+# define LT_ELFCLASS2 ELFCLASS64
|
|
|
f84355 |
+# define LT_ELF_MACHINE2 EM_PPC64
|
|
|
f84355 |
|
|
|
f84355 |
# ifdef __LITTLE_ENDIAN__
|
|
|
f84355 |
-# define BREAKPOINT_VALUE { 0x08, 0x00, 0xe0, 0x7f }
|
|
|
f84355 |
-# define ARCH_ENDIAN_LITTLE
|
|
|
f84355 |
+# define BREAKPOINT_VALUE { 0x08, 0x00, 0xe0, 0x7f }
|
|
|
f84355 |
+# define ARCH_ENDIAN_LITTLE
|
|
|
f84355 |
# else
|
|
|
f84355 |
-# define BREAKPOINT_VALUE { 0x7f, 0xe0, 0x00, 0x08 }
|
|
|
f84355 |
-# define ARCH_SUPPORTS_OPD
|
|
|
f84355 |
-# define ARCH_ENDIAN_BIG
|
|
|
f84355 |
+# define BREAKPOINT_VALUE { 0x7f, 0xe0, 0x00, 0x08 }
|
|
|
f84355 |
+# define ARCH_SUPPORTS_OPD
|
|
|
f84355 |
+# define ARCH_ENDIAN_BIG
|
|
|
f84355 |
# endif
|
|
|
f84355 |
|
|
|
f84355 |
-# if _CALL_ELF != 2
|
|
|
f84355 |
-# define ARCH_SUPPORTS_OPD
|
|
|
f84355 |
-# define STACK_FRAME_OVERHEAD 112
|
|
|
f84355 |
+# if !defined(_CALL_ELF) || _CALL_ELF < 2
|
|
|
f84355 |
+# define ARCH_SUPPORTS_OPD
|
|
|
f84355 |
+# define STACK_FRAME_OVERHEAD 112
|
|
|
f84355 |
# ifndef EF_PPC64_ABI
|
|
|
f84355 |
-# define EF_PPC64_ABI 3
|
|
|
f84355 |
+# define EF_PPC64_ABI 3
|
|
|
f84355 |
# endif
|
|
|
f84355 |
-# else /* _CALL_ELF == 2 ABIv2 */
|
|
|
f84355 |
-# define STACK_FRAME_OVERHEAD 32
|
|
|
f84355 |
+# elif _CALL_ELF == 2 /* ELFv2 ABI */
|
|
|
f84355 |
+# define STACK_FRAME_OVERHEAD 32
|
|
|
f84355 |
+# else
|
|
|
f84355 |
+# error Unsupported PowerPC64 ABI.
|
|
|
f84355 |
# endif /* CALL_ELF */
|
|
|
f84355 |
|
|
|
f84355 |
#else
|
|
|
f84355 |
-#define BREAKPOINT_VALUE { 0x7f, 0xe0, 0x00, 0x08 }
|
|
|
f84355 |
-#define ARCH_ENDIAN_BIG
|
|
|
f84355 |
+# define STACK_FRAME_OVERHEAD 112
|
|
|
f84355 |
+# define BREAKPOINT_VALUE { 0x7f, 0xe0, 0x00, 0x08 }
|
|
|
f84355 |
+# define ARCH_ENDIAN_BIG
|
|
|
f84355 |
# ifndef EF_PPC64_ABI
|
|
|
f84355 |
-# define EF_PPC64_ABI 3
|
|
|
f84355 |
+# define EF_PPC64_ABI 3
|
|
|
f84355 |
# endif
|
|
|
f84355 |
#endif /* __powerpc64__ */
|
|
|
f84355 |
|
|
|
f84355 |
+#ifdef _CALL_ELF
|
|
|
f84355 |
+enum { ppc64_call_elf_abi = _CALL_ELF };
|
|
|
f84355 |
+#else
|
|
|
f84355 |
+enum { ppc64_call_elf_abi = 0 };
|
|
|
f84355 |
+#endif
|
|
|
f84355 |
+
|
|
|
f84355 |
#define ARCH_HAVE_SW_SINGLESTEP
|
|
|
f84355 |
#define ARCH_HAVE_ADD_PLT_ENTRY
|
|
|
f84355 |
#define ARCH_HAVE_ADD_FUNC_ENTRY
|
|
|
f84355 |
diff --git a/sysdeps/linux-gnu/ppc/fetch.c b/sysdeps/linux-gnu/ppc/fetch.c
|
|
|
f84355 |
index c9381c3..c6cbd71 100644
|
|
|
f84355 |
--- a/sysdeps/linux-gnu/ppc/fetch.c
|
|
|
f84355 |
+++ b/sysdeps/linux-gnu/ppc/fetch.c
|
|
|
f84355 |
@@ -1,6 +1,6 @@
|
|
|
f84355 |
/*
|
|
|
f84355 |
* This file is part of ltrace.
|
|
|
f84355 |
- * Copyright (C) 2012 Petr Machata, Red Hat Inc.
|
|
|
f84355 |
+ * Copyright (C) 2012, 2014 Petr Machata, Red Hat Inc.
|
|
|
f84355 |
*
|
|
|
f84355 |
* This program is free software; you can redistribute it and/or
|
|
|
f84355 |
* modify it under the terms of the GNU General Public License as
|
|
|
f84355 |
@@ -23,6 +23,7 @@
|
|
|
f84355 |
#include <stdlib.h>
|
|
|
f84355 |
#include <string.h>
|
|
|
f84355 |
#include <sys/ucontext.h>
|
|
|
f84355 |
+#include <stdio.h>
|
|
|
f84355 |
|
|
|
f84355 |
#include "backend.h"
|
|
|
f84355 |
#include "fetch.h"
|
|
|
f84355 |
@@ -57,7 +58,7 @@ struct fetch_context {
|
|
|
f84355 |
arch_addr_t stack_pointer;
|
|
|
f84355 |
int greg;
|
|
|
f84355 |
int freg;
|
|
|
f84355 |
- int ret_struct;
|
|
|
f84355 |
+ bool ret_struct;
|
|
|
f84355 |
|
|
|
f84355 |
union {
|
|
|
f84355 |
gregs32_t r32;
|
|
|
f84355 |
@@ -65,11 +66,29 @@ struct fetch_context {
|
|
|
f84355 |
} regs;
|
|
|
f84355 |
struct fpregs_t fpregs;
|
|
|
f84355 |
int vgreg;
|
|
|
f84355 |
- int struct_size;
|
|
|
f84355 |
- int struct_hfa_size;
|
|
|
f84355 |
- int struct_hfa_count;
|
|
|
f84355 |
};
|
|
|
f84355 |
|
|
|
f84355 |
+static bool
|
|
|
f84355 |
+is_eligible_hfa(struct arg_type_info *info,
|
|
|
f84355 |
+ struct arg_type_info **hfa_infop, size_t *hfa_countp)
|
|
|
f84355 |
+{
|
|
|
f84355 |
+ size_t hfa_count;
|
|
|
f84355 |
+ struct arg_type_info *hfa_info = type_get_hfa_type(info, &hfa_count);
|
|
|
f84355 |
+
|
|
|
f84355 |
+ if (hfa_info != NULL && hfa_count <= 8
|
|
|
f84355 |
+ && (hfa_info->type == ARGTYPE_FLOAT
|
|
|
f84355 |
+ || hfa_info->type == ARGTYPE_DOUBLE)) {
|
|
|
f84355 |
+
|
|
|
f84355 |
+ if (hfa_infop != NULL)
|
|
|
f84355 |
+ *hfa_infop = hfa_info;
|
|
|
f84355 |
+ if (hfa_countp != NULL)
|
|
|
f84355 |
+ *hfa_countp = hfa_count;
|
|
|
f84355 |
+ return true;
|
|
|
f84355 |
+ }
|
|
|
f84355 |
+
|
|
|
f84355 |
+ return false;
|
|
|
f84355 |
+}
|
|
|
f84355 |
+
|
|
|
f84355 |
static int
|
|
|
f84355 |
fetch_context_init(struct process *proc, struct fetch_context *context)
|
|
|
f84355 |
{
|
|
|
f84355 |
@@ -125,30 +144,37 @@ arch_fetch_arg_init(enum tof type, struct process *proc,
|
|
|
f84355 |
}
|
|
|
f84355 |
|
|
|
f84355 |
context->vgreg = context->greg;
|
|
|
f84355 |
- context->struct_size = 0;
|
|
|
f84355 |
- context->struct_hfa_size = 0;
|
|
|
f84355 |
- context->struct_hfa_count = 0;
|
|
|
f84355 |
|
|
|
f84355 |
/* Aggregates or unions of any length, and character strings
|
|
|
f84355 |
* of length longer than 8 bytes, will be returned in a
|
|
|
f84355 |
* storage buffer allocated by the caller. The caller will
|
|
|
f84355 |
* pass the address of this buffer as a hidden first argument
|
|
|
f84355 |
* in r3, causing the first explicit argument to be passed in
|
|
|
f84355 |
- * r4. */
|
|
|
f84355 |
- context->ret_struct = ret_info->type == ARGTYPE_STRUCT;
|
|
|
f84355 |
- if (context->ret_struct) {
|
|
|
f84355 |
-#if _CALL_ELF == 2
|
|
|
f84355 |
- /* if R3 points to stack, parameters will be in R4. */
|
|
|
f84355 |
- uint64_t pstack_end = ptrace(PTRACE_PEEKTEXT, proc->pid,
|
|
|
f84355 |
- proc->stack_pointer, 0);
|
|
|
f84355 |
- if (((arch_addr_t)context->regs.r64[3] > proc->stack_pointer)
|
|
|
f84355 |
- && (context->regs.r64[3] < pstack_end)) {
|
|
|
f84355 |
+ * r4.
|
|
|
f84355 |
+ */
|
|
|
f84355 |
+
|
|
|
f84355 |
+ context->ret_struct = false;
|
|
|
f84355 |
+
|
|
|
f84355 |
+ if (ppc64_call_elf_abi == 2) {
|
|
|
f84355 |
+ /* With ELFv2 ABI, aggregates that consist
|
|
|
f84355 |
+ * (recursively) only of members of the same
|
|
|
f84355 |
+ * floating-point or vector type, are passed in a
|
|
|
f84355 |
+ * series of floating-point resp. vector registers.
|
|
|
f84355 |
+ * Additionally, when returning any aggregate of up to
|
|
|
f84355 |
+ * 16 bytes, general-purpose registers are used. */
|
|
|
f84355 |
+
|
|
|
f84355 |
+ if (ret_info->type == ARGTYPE_STRUCT
|
|
|
f84355 |
+ && ! is_eligible_hfa(ret_info, NULL, NULL)
|
|
|
f84355 |
+ && type_sizeof(proc, ret_info) > 16) {
|
|
|
f84355 |
+
|
|
|
f84355 |
+ context->ret_struct = true;
|
|
|
f84355 |
context->greg++;
|
|
|
f84355 |
context->stack_pointer += 8;
|
|
|
f84355 |
}
|
|
|
f84355 |
-#else
|
|
|
f84355 |
+
|
|
|
f84355 |
+ } else if (ret_info->type == ARGTYPE_STRUCT) {
|
|
|
f84355 |
+ context->ret_struct = true;
|
|
|
f84355 |
context->greg++;
|
|
|
f84355 |
-#endif
|
|
|
f84355 |
}
|
|
|
f84355 |
|
|
|
f84355 |
return context;
|
|
|
f84355 |
@@ -176,17 +202,16 @@ allocate_stack_slot(struct fetch_context *ctx, struct process *proc,
|
|
|
f84355 |
|
|
|
f84355 |
size_t a = type_alignof(proc, info);
|
|
|
f84355 |
size_t off = 0;
|
|
|
f84355 |
- if (proc->e_machine == EM_PPC && a < 4)
|
|
|
f84355 |
- a = 4;
|
|
|
f84355 |
-#if _CALL_ELF == 2
|
|
|
f84355 |
- else if (proc->e_machine == EM_PPC64 && sz == 4 && is_hfa_type)
|
|
|
f84355 |
+ if (proc->e_machine == EM_PPC && a < 4) {
|
|
|
f84355 |
a = 4;
|
|
|
f84355 |
- else
|
|
|
f84355 |
- a = 8;
|
|
|
f84355 |
-#else
|
|
|
f84355 |
- else if (proc->e_machine == EM_PPC64 && a < 8)
|
|
|
f84355 |
-#endif
|
|
|
f84355 |
+ } else if (ppc64_call_elf_abi == 2) {
|
|
|
f84355 |
+ if (proc->e_machine == EM_PPC64 && sz == 4 && is_hfa_type) {
|
|
|
f84355 |
+ a = 4;
|
|
|
f84355 |
+ } else
|
|
|
f84355 |
+ a = 8;
|
|
|
f84355 |
+ } else if (proc->e_machine == EM_PPC64 && a < 8) {
|
|
|
f84355 |
a = 8;
|
|
|
f84355 |
+ }
|
|
|
f84355 |
|
|
|
f84355 |
/* XXX Remove the two double casts when arch_addr_t
|
|
|
f84355 |
* becomes integral type. */
|
|
|
f84355 |
@@ -259,18 +284,19 @@ allocate_gpr(struct fetch_context *ctx, struct process *proc,
|
|
|
f84355 |
if (sz == (size_t)-1)
|
|
|
f84355 |
return -1;
|
|
|
f84355 |
assert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
|
|
|
f84355 |
-#if _CALL_ELF == 2
|
|
|
f84355 |
- /* Consume the stack slot corresponding to this arg. */
|
|
|
f84355 |
- if ((sz + off) >= 8)
|
|
|
f84355 |
- ctx->greg++;
|
|
|
f84355 |
|
|
|
f84355 |
- if (is_hfa_type)
|
|
|
f84355 |
- ctx->stack_pointer += sz;
|
|
|
f84355 |
- else
|
|
|
f84355 |
- ctx->stack_pointer += 8;
|
|
|
f84355 |
-#else
|
|
|
f84355 |
- ctx->greg++;
|
|
|
f84355 |
-#endif
|
|
|
f84355 |
+ if (ppc64_call_elf_abi == 2) {
|
|
|
f84355 |
+ /* Consume the stack slot corresponding to this arg. */
|
|
|
f84355 |
+ if ((sz + off) >= 8)
|
|
|
f84355 |
+ ctx->greg++;
|
|
|
f84355 |
+
|
|
|
f84355 |
+ if (is_hfa_type)
|
|
|
f84355 |
+ ctx->stack_pointer += sz;
|
|
|
f84355 |
+ else
|
|
|
f84355 |
+ ctx->stack_pointer += 8;
|
|
|
f84355 |
+ } else {
|
|
|
f84355 |
+ ctx->greg++;
|
|
|
f84355 |
+ }
|
|
|
f84355 |
|
|
|
f84355 |
if (valuep == NULL)
|
|
|
f84355 |
return 0;
|
|
|
f84355 |
@@ -326,7 +352,6 @@ allocate_float(struct fetch_context *ctx, struct process *proc,
|
|
|
f84355 |
return allocate_stack_slot(ctx, proc, info, valuep, is_hfa_type);
|
|
|
f84355 |
}
|
|
|
f84355 |
|
|
|
f84355 |
-#if _CALL_ELF == 2
|
|
|
f84355 |
static int
|
|
|
f84355 |
allocate_hfa(struct fetch_context *ctx, struct process *proc,
|
|
|
f84355 |
struct arg_type_info *info, struct value *valuep,
|
|
|
f84355 |
@@ -336,27 +361,27 @@ allocate_hfa(struct fetch_context *ctx, struct process *proc,
|
|
|
f84355 |
if (sz == (size_t)-1)
|
|
|
f84355 |
return -1;
|
|
|
f84355 |
|
|
|
f84355 |
- ctx->struct_hfa_size += sz;
|
|
|
f84355 |
-
|
|
|
f84355 |
/* There are two changes regarding structure return types:
|
|
|
f84355 |
- * * heterogeneous float/vector structs are returned
|
|
|
f84355 |
- * in (multiple) FP/vector registers,
|
|
|
f84355 |
- * instead of via implicit reference.
|
|
|
f84355 |
- * * small structs (up to 16 bytes) are return
|
|
|
f84355 |
- * in one or two GPRs, instead of via implicit reference.
|
|
|
f84355 |
+ * * heterogeneous float/vector structs are returned in
|
|
|
f84355 |
+ * (multiple) FP/vector registers, instead of via implicit
|
|
|
f84355 |
+ * reference.
|
|
|
f84355 |
+ * * small structs (up to 16 bytes) are return in one or two
|
|
|
f84355 |
+ * GPRs, instead of via implicit reference.
|
|
|
f84355 |
*
|
|
|
f84355 |
* Other structures (larger than 16 bytes, not heterogeneous)
|
|
|
f84355 |
* are still returned via implicit reference (i.e. a pointer
|
|
|
f84355 |
* to memory where to return the struct being passed in r3).
|
|
|
f84355 |
- * Of course, whether or not an implicit reference pointer
|
|
|
f84355 |
- * is present will shift the remaining arguments,
|
|
|
f84355 |
- * so you need to get this right for ELFv2 in order
|
|
|
f84355 |
- * to get the arguments correct.
|
|
|
f84355 |
+ * Of course, whether or not an implicit reference pointer is
|
|
|
f84355 |
+ * present will shift the remaining arguments, so you need to
|
|
|
f84355 |
+ * get this right for ELFv2 in order to get the arguments
|
|
|
f84355 |
+ * correct.
|
|
|
f84355 |
+ *
|
|
|
f84355 |
* If an actual parameter is known to correspond to an HFA
|
|
|
f84355 |
* formal parameter, each element is passed in the next
|
|
|
f84355 |
* available floating-point argument register starting at fp1
|
|
|
f84355 |
* until the fp13. The remaining elements of the aggregate are
|
|
|
f84355 |
- * passed on the stack. */
|
|
|
f84355 |
+ * passed on the stack.
|
|
|
f84355 |
+ */
|
|
|
f84355 |
size_t slot_off = 0;
|
|
|
f84355 |
|
|
|
f84355 |
unsigned char *buf = value_reserve(valuep, sz);
|
|
|
f84355 |
@@ -366,26 +391,17 @@ allocate_hfa(struct fetch_context *ctx, struct process *proc,
|
|
|
f84355 |
struct arg_type_info *hfa_info = type_get_simple(hfa_type);
|
|
|
f84355 |
size_t hfa_sz = type_sizeof(proc, hfa_info);
|
|
|
f84355 |
|
|
|
f84355 |
- if (hfa_count > 8)
|
|
|
f84355 |
- ctx->struct_hfa_count += hfa_count;
|
|
|
f84355 |
-
|
|
|
f84355 |
while (hfa_count > 0 && ctx->freg <= 13) {
|
|
|
f84355 |
- int rc;
|
|
|
f84355 |
struct value tmp;
|
|
|
f84355 |
-
|
|
|
f84355 |
value_init(&tmp, proc, NULL, hfa_info, 0);
|
|
|
f84355 |
+ int rc = allocate_float(ctx, proc, hfa_info,
|
|
|
f84355 |
+ &tmp, slot_off, true);
|
|
|
f84355 |
+ if (rc == 0)
|
|
|
f84355 |
+ memcpy(buf, value_get_data(&tmp, NULL), hfa_sz);
|
|
|
f84355 |
+ value_destroy(&tmp);
|
|
|
f84355 |
|
|
|
f84355 |
- /* Hetereogeneous struct - get value on GPR or stack. */
|
|
|
f84355 |
- if (((hfa_type == ARGTYPE_FLOAT
|
|
|
f84355 |
- || hfa_type == ARGTYPE_DOUBLE)
|
|
|
f84355 |
- && hfa_count <= 8))
|
|
|
f84355 |
- rc = allocate_float(ctx, proc, hfa_info, &tmp,
|
|
|
f84355 |
- slot_off, true);
|
|
|
f84355 |
- else
|
|
|
f84355 |
- rc = allocate_gpr(ctx, proc, hfa_info, &tmp,
|
|
|
f84355 |
- slot_off, true);
|
|
|
f84355 |
-
|
|
|
f84355 |
- memcpy(buf, value_get_data(&tmp, NULL), hfa_sz);
|
|
|
f84355 |
+ if (rc < 0)
|
|
|
f84355 |
+ return -1;
|
|
|
f84355 |
|
|
|
f84355 |
slot_off += hfa_sz;
|
|
|
f84355 |
buf += hfa_sz;
|
|
|
f84355 |
@@ -394,17 +410,13 @@ allocate_hfa(struct fetch_context *ctx, struct process *proc,
|
|
|
f84355 |
slot_off = 0;
|
|
|
f84355 |
ctx->vgreg++;
|
|
|
f84355 |
}
|
|
|
f84355 |
-
|
|
|
f84355 |
- value_destroy(&tmp);
|
|
|
f84355 |
- if (rc < 0)
|
|
|
f84355 |
- return -1;
|
|
|
f84355 |
}
|
|
|
f84355 |
if (hfa_count == 0)
|
|
|
f84355 |
return 0;
|
|
|
f84355 |
|
|
|
f84355 |
/* if no remaining FP, GPR corresponding to slot is used
|
|
|
f84355 |
- * Mostly it is in part of r10. */
|
|
|
f84355 |
- if (ctx->struct_hfa_size <= 64 && ctx->vgreg == 10) {
|
|
|
f84355 |
+ * Mostly it is in part of r10. */
|
|
|
f84355 |
+ if (ctx->vgreg == 10) {
|
|
|
f84355 |
while (ctx->vgreg <= 10) {
|
|
|
f84355 |
struct value tmp;
|
|
|
f84355 |
value_init(&tmp, proc, NULL, hfa_info, 0);
|
|
|
f84355 |
@@ -428,11 +440,8 @@ allocate_hfa(struct fetch_context *ctx, struct process *proc,
|
|
|
f84355 |
}
|
|
|
f84355 |
}
|
|
|
f84355 |
|
|
|
f84355 |
- if (hfa_count == 0)
|
|
|
f84355 |
- return 0;
|
|
|
f84355 |
-
|
|
|
f84355 |
/* Remaining values are on stack */
|
|
|
f84355 |
- while (hfa_count) {
|
|
|
f84355 |
+ while (hfa_count > 0) {
|
|
|
f84355 |
struct value tmp;
|
|
|
f84355 |
value_init(&tmp, proc, NULL, hfa_info, 0);
|
|
|
f84355 |
|
|
|
f84355 |
@@ -444,7 +453,6 @@ allocate_hfa(struct fetch_context *ctx, struct process *proc,
|
|
|
f84355 |
}
|
|
|
f84355 |
return 0;
|
|
|
f84355 |
}
|
|
|
f84355 |
-#endif
|
|
|
f84355 |
|
|
|
f84355 |
static int
|
|
|
f84355 |
allocate_argument(struct fetch_context *ctx, struct process *proc,
|
|
|
f84355 |
@@ -459,24 +467,20 @@ allocate_argument(struct fetch_context *ctx, struct process *proc,
|
|
|
f84355 |
case ARGTYPE_FLOAT:
|
|
|
f84355 |
case ARGTYPE_DOUBLE:
|
|
|
f84355 |
return allocate_float(ctx, proc, info, valuep,
|
|
|
f84355 |
- 8 - type_sizeof(proc,info), false);
|
|
|
f84355 |
+ 8 - type_sizeof(proc,info), false);
|
|
|
f84355 |
|
|
|
f84355 |
case ARGTYPE_STRUCT:
|
|
|
f84355 |
if (proc->e_machine == EM_PPC) {
|
|
|
f84355 |
if (value_pass_by_reference(valuep) < 0)
|
|
|
f84355 |
return -1;
|
|
|
f84355 |
- } else {
|
|
|
f84355 |
-#if _CALL_ELF == 2
|
|
|
f84355 |
+ } else if (ppc64_call_elf_abi == 2) {
|
|
|
f84355 |
struct arg_type_info *hfa_info;
|
|
|
f84355 |
- size_t hfa_size;
|
|
|
f84355 |
- hfa_info = type_get_hfa_type(info, &hfa_size);
|
|
|
f84355 |
- if (hfa_info != NULL ) {
|
|
|
f84355 |
- size_t sz = type_sizeof(proc, info);
|
|
|
f84355 |
- ctx->struct_size += sz;
|
|
|
f84355 |
+ size_t hfa_count;
|
|
|
f84355 |
+ if (is_eligible_hfa(info, &hfa_info, &hfa_count)) {
|
|
|
f84355 |
return allocate_hfa(ctx, proc, info, valuep,
|
|
|
f84355 |
- hfa_info->type, hfa_size);
|
|
|
f84355 |
+ hfa_info->type, hfa_count);
|
|
|
f84355 |
}
|
|
|
f84355 |
-#endif
|
|
|
f84355 |
+ } else {
|
|
|
f84355 |
/* PPC64: Fixed size aggregates and unions passed by
|
|
|
f84355 |
* value are mapped to as many doublewords of the
|
|
|
f84355 |
* parameter save area as the value uses in memory.
|
|
|
f84355 |
@@ -510,9 +514,6 @@ allocate_argument(struct fetch_context *ctx, struct process *proc,
|
|
|
f84355 |
if (sz == (size_t)-1)
|
|
|
f84355 |
return -1;
|
|
|
f84355 |
|
|
|
f84355 |
- if (ctx->ret_struct)
|
|
|
f84355 |
- ctx->struct_size += sz;
|
|
|
f84355 |
-
|
|
|
f84355 |
size_t slots = (sz + width - 1) / width; /* Round up. */
|
|
|
f84355 |
unsigned char *buf = value_reserve(valuep, slots * width);
|
|
|
f84355 |
if (buf == NULL)
|
|
|
f84355 |
@@ -605,19 +606,7 @@ arch_fetch_retval(struct fetch_context *ctx, enum tof type,
|
|
|
f84355 |
if (fetch_context_init(proc, ctx) < 0)
|
|
|
f84355 |
return -1;
|
|
|
f84355 |
|
|
|
f84355 |
-#if _CALL_ELF == 2
|
|
|
f84355 |
- void *ptr = (void *)(ctx->regs.r64[1]+32);
|
|
|
f84355 |
- uint64_t val = ptrace(PTRACE_PEEKTEXT, proc->pid, ptr, 0);
|
|
|
f84355 |
-
|
|
|
f84355 |
- if (ctx->ret_struct
|
|
|
f84355 |
- && ((ctx->struct_size > 64
|
|
|
f84355 |
- || ctx->struct_hfa_count > 8
|
|
|
f84355 |
- || (ctx->struct_hfa_size == 0 && ctx->struct_size > 56)
|
|
|
f84355 |
- || (ctx->regs.r64[3] == ctx->regs.r64[1]+32)
|
|
|
f84355 |
- || (ctx->regs.r64[3] == val )))) {
|
|
|
f84355 |
-#else
|
|
|
f84355 |
if (ctx->ret_struct) {
|
|
|
f84355 |
-#endif
|
|
|
f84355 |
assert(info->type == ARGTYPE_STRUCT);
|
|
|
f84355 |
|
|
|
f84355 |
uint64_t addr = read_gpr(ctx, proc, 3);
|