Here after find the 3 patches produced to enable ppc64el arch with ABIv2
applying on ltrace 0.7.2/0.7.3/0.7.3.4 trees

1st patch is mostly handling endianess and was checked on RH ABIv1
2nd patch enable ABIv2 and was tested on Suze
3rd patch fix Debian/Ubuntu dynamic library load

Of course comments are welcome, knowing that the change in the dev. tree
would allow to rework and clean the code if needed.

-- Thierry Fauck @ linux.vnet.ibm.com
From: Thierry Fauck <[email protected]>
Date: Thu, 30 Jan 2014 14:44:10 +0100

First set of changes for ltrace and ppc64le arch for ABI V1

Signed-off-by: Thierry Fauck <[email protected]>

 {ltrace-0.7.3.orig => ltrace-0.7.3}/configure.ac                  | 3 ++-
 {ltrace-0.7.3.orig => ltrace-0.7.3}/sysdeps/linux-gnu/ppc/arch.h  | 8 +++++++-
 {ltrace-0.7.3.orig => ltrace-0.7.3}/sysdeps/linux-gnu/ppc/fetch.c | 2 ++
 {ltrace-0.7.3.orig => ltrace-0.7.3}/sysdeps/linux-gnu/ppc/plt.c   | 4 ++++
 {ltrace-0.7.3.orig => ltrace-0.7.3}/sysdeps/linux-gnu/ppc/trace.c | 8 ++++++++
 5 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/ltrace-0.7.3.orig/configure.ac b/ltrace-0.7.3/configure.ac
index 95027d5..dabdd11 100644
--- a/ltrace-0.7.3.orig/configure.ac
+++ b/ltrace-0.7.3/configure.ac
@@ -42,7 +42,7 @@ case "${host_cpu}" in
     arm*|sa110)		HOST_CPU="arm" ;;
     cris*)		HOST_CPU="cris" ;;
     mips*)		HOST_CPU="mips" ;;
-    powerpc|powerpc64)	HOST_CPU="ppc" ;;
+    powerpc|powerpc64|powerpc64le)	HOST_CPU="ppc" ;;
     sun4u|sparc64)	HOST_CPU="sparc" ;;
     s390x)		HOST_CPU="s390" ;;
     i?86|x86_64)	HOST_CPU="x86" ;;
@@ -168,6 +168,7 @@ if test x"$enable_libunwind" = xyes; then
       i?86)               UNWIND_ARCH="x86" ;;
       powerpc)            UNWIND_ARCH="ppc32" ;;
       powerpc64)          UNWIND_ARCH="ppc64" ;;
+      powerpc64le)        UNWIND_ARCH="ppc64" ;;
       mips*)              UNWIND_ARCH="mips" ;;
       *)                  UNWIND_ARCH="${host_cpu}" ;;
   esac
diff --git a/ltrace-0.7.3.orig/sysdeps/linux-gnu/ppc/arch.h b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/arch.h
index fb8768a..edabe2e 100644
--- a/ltrace-0.7.3.orig/sysdeps/linux-gnu/ppc/arch.h
+++ b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/arch.h
@@ -27,6 +27,7 @@
 #define BREAKPOINT_VALUE { 0x7f, 0xe0, 0x00, 0x08 }
 #define BREAKPOINT_LENGTH 4
 #define DECR_PC_AFTER_BREAK 0
+#define ARCH_ENDIAN_BIG
 
 #define LT_ELFCLASS	ELFCLASS32
 #define LT_ELF_MACHINE	EM_PPC
@@ -35,6 +36,12 @@
 #define LT_ELFCLASS2	ELFCLASS64
 #define LT_ELF_MACHINE2	EM_PPC64
 #define ARCH_SUPPORTS_OPD
+#ifdef __LITTLE_ENDIAN__
+#undef BREAKPOINT_VALUE
+#define BREAKPOINT_VALUE { 0x08, 0x00, 0xe0, 0x7f }
+#define ARCH_ENDIAN_LITTLE
+#undef ARCH_ENDIAN_BIG
+#endif
 #endif
 
 #define ARCH_HAVE_ATOMIC_SINGLESTEP
@@ -42,7 +49,6 @@
 #define ARCH_HAVE_TRANSLATE_ADDRESS
 #define ARCH_HAVE_DYNLINK_DONE
 #define ARCH_HAVE_FETCH_ARG
-#define ARCH_ENDIAN_BIG
 #define ARCH_HAVE_SIZEOF
 #define ARCH_HAVE_ALIGNOF
 
diff --git a/ltrace-0.7.3.orig/sysdeps/linux-gnu/ppc/fetch.c b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/fetch.c
index 9963a1e..3b62fa0 100644
--- a/ltrace-0.7.3.orig/sysdeps/linux-gnu/ppc/fetch.c
+++ b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/fetch.c
@@ -364,6 +364,7 @@ allocate_argument(struct fetch_context *ctx, struct Process *proc,
 	}
 
 	/* Small values need post-processing.  */
+#ifndef __LITTLE_ENDIAN__
 	if (sz < width) {
 		switch (info->type) {
 		default:
@@ -394,6 +395,7 @@ allocate_argument(struct fetch_context *ctx, struct Process *proc,
 			break;
 		}
 	}
+#endif
 
 	return 0;
 }
diff --git a/ltrace-0.7.3.orig/sysdeps/linux-gnu/ppc/plt.c b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/plt.c
index f83f087..9097c27 100644
--- a/ltrace-0.7.3.orig/sysdeps/linux-gnu/ppc/plt.c
+++ b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/plt.c
@@ -221,7 +221,11 @@ arch_dynlink_done(struct Process *proc)
 		if ((insn1 & BRANCH_MASK) == B_INSN
 		    || ((insn2 & BRANCH_MASK) == B_INSN
 			/* XXX double cast  */
+#ifdef __LITTLE_ENDIAN__
+			&& (ppc_branch_dest(libsym->enter_addr + 4, insn1)
+#else
 			&& (ppc_branch_dest(libsym->enter_addr + 4, insn2)
+#endif
 			    == (void*)(long)libsym->lib->arch.pltgot_addr)))
 			mark_as_resolved(libsym, libsym->arch.resolved_value);
 
diff --git a/ltrace-0.7.3.orig/sysdeps/linux-gnu/ppc/trace.c b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/trace.c
index 4357a1e..df53578 100644
--- a/ltrace-0.7.3.orig/sysdeps/linux-gnu/ppc/trace.c
+++ b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/trace.c
@@ -64,7 +64,11 @@ syscall_p(Process *proc, int status, int *sysnum) {
 	    && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
 		long pc = (long)get_instruction_pointer(proc);
 		int insn =
+#ifdef __LITTLE_ENDIAN__
+		    (int)ptrace(PTRACE_PEEKTEXT, proc->pid, pc - sizeof(int),
+#else
 		    (int)ptrace(PTRACE_PEEKTEXT, proc->pid, pc - sizeof(long),
+#endif
 				0);
 
 		if (insn == SYSCALL_INSN) {
@@ -128,7 +132,11 @@ arch_atomic_singlestep(struct Process *proc, struct breakpoint *sbp,
 			return -1;
 		uint32_t insn;
 #ifdef __powerpc64__
+#ifdef __LITTLE_ENDIAN__
+		insn = (uint32_t) l ;
+#else
 		insn = l >> 32;
+#endif
 #else
 		insn = l;
 #endif
>From 09e03e58e58325c5099188a798c8e119277314cf Mon Sep 17 00:00:00 2001
From: Michel Normand <[email protected]>
Date: Thu, 20 Feb 2014 14:44:10 +0100
Subject: [PATCH 2/3] ltrace ppc64le ABIv2

From: Thierry Fauck <[email protected]>

Patches to enable ppc64el arch and ABI V2
	. Remove use of .opd
	. Correct parameters location

Signed-off-by: Thierry Fauck <[email protected]>
Signed-off-by: Guy Menanteau <[email protected]>

 {ltrace.0.7.3-v1 => ltrace-0.7.3}/ltrace-elf.c     |   4 +
 .../sysdeps/linux-gnu/ppc/arch.h                   |   3 +
 .../sysdeps/linux-gnu/ppc/fetch.c                  | 193 ++++++++++++++++++++-
 .../sysdeps/linux-gnu/ppc/plt.c                    |  14 +-
 .../sysdeps/linux-gnu/ppc/trace.c                  |   2 +
 5 files changed, 212 insertions(+), 4 deletions(-)

diff --git a/ltrace.0.7.3-v1/ltrace-elf.c b/ltrace-0.7.3/ltrace-elf.c
index c571d2a..4b8b0bc 100644
--- a/ltrace.0.7.3-v1/ltrace-elf.c
+++ b/ltrace-0.7.3/ltrace-elf.c
@@ -714,6 +714,10 @@ populate_this_symtab(struct Process *proc, const char *filename,
 			continue;
 		}
 
+#if defined(__powerpc64__) && _CALL_ELF == 2
+		naddr += PPC64_LOCAL_ENTRY_OFFSET (sym.st_other);
+#endif
+
 		char *full_name;
 		int own_full_name = 1;
 		if (name_copy == NULL) {
diff --git a/ltrace.0.7.3-v1/sysdeps/linux-gnu/ppc/arch.h b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/arch.h
index edabe2e..3505cd4 100644
--- a/ltrace.0.7.3-v1/sysdeps/linux-gnu/ppc/arch.h
+++ b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/arch.h
@@ -41,6 +41,9 @@
 #define BREAKPOINT_VALUE { 0x08, 0x00, 0xe0, 0x7f }
 #define ARCH_ENDIAN_LITTLE
 #undef ARCH_ENDIAN_BIG
+#if _CALL_ELF == 2
+#undef ARCH_SUPPORTS_OPD
+#endif
 #endif
 #endif
 
diff --git a/ltrace.0.7.3-v1/sysdeps/linux-gnu/ppc/fetch.c b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/fetch.c
index 3b62fa0..1e5a584 100644
--- a/ltrace.0.7.3-v1/sysdeps/linux-gnu/ppc/fetch.c
+++ b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/fetch.c
@@ -65,16 +65,38 @@ struct fetch_context {
 
 };
 
+enum homogeneous_type {
+	NOINIT = 0,
+	HETEROGENEOUS,
+	HOMOGENEOUS,
+	HOMOGENEOUS_NESTED_FLOAT,
+};
+
+struct struct_attributes {
+	struct arg_type_info *info;
+	enum arg_type type;
+	size_t nb_elements;
+	enum homogeneous_type homogeneous;
+};
+
+
 static int
 fetch_context_init(struct Process *proc, struct fetch_context *context)
 {
 	context->greg = 3;
 	context->freg = 1;
 
+#if _CALL_ELF == 2
+#define STACK_FRAME_OVERHEAD 96
+#else
+#define STACK_FRAME_OVERHEAD 112
+#endif
+
 	if (proc->e_machine == EM_PPC)
 		context->stack_pointer = proc->stack_pointer + 8;
 	else
-		context->stack_pointer = proc->stack_pointer + 112;
+		context->stack_pointer = proc->stack_pointer + 
+			STACK_FRAME_OVERHEAD;
 
 	/* When ltrace is 64-bit, we might use PTRACE_GETREGS to
 	 * obtain 64-bit as well as 32-bit registers.  But if we do it
@@ -107,6 +129,57 @@ fetch_context_init(struct Process *proc, struct fetch_context *context)
 	return 0;
 }
 
+#if  _CALL_ELF == 2
+static int
+get_struct_attribut(struct arg_type_info *info, struct Process *proc,
+		    size_t *size_of, struct struct_attributes *struct_attr)
+{
+	size_t n = type_aggregate_size(info);
+	if (n == (size_t)-1)
+		return ARGTYPE_VOID;
+
+	enum arg_type type = ARGTYPE_VOID;
+
+	while (n-- > 0) {
+		struct arg_type_info *emt = type_element(info, n);
+		enum arg_type emt_type = emt->type;
+
+		if (emt_type != ARGTYPE_STRUCT) {
+			(struct_attr->nb_elements)++;
+			if (struct_attr->homogeneous == NOINIT) {
+				struct_attr->info = emt;
+				struct_attr->type = emt_type;
+
+				if (emt_type == ARGTYPE_DOUBLE ||
+				   emt_type == ARGTYPE_FLOAT)
+					struct_attr->homogeneous =
+					   HOMOGENEOUS_NESTED_FLOAT;
+				else
+					struct_attr->homogeneous = HOMOGENEOUS;
+			} else {
+				if (struct_attr->type != emt_type)
+				   struct_attr->homogeneous = HETEROGENEOUS;
+			}
+		}
+
+		if (emt_type == ARGTYPE_STRUCT) {
+			emt_type = get_struct_attribut(emt, proc, size_of,
+					struct_attr);
+		} else {
+			size_t size = type_sizeof(proc, emt);
+			if (size == (size_t)-1)
+				return -1;
+			*size_of += size;
+		}
+
+		type = emt_type;
+	}
+
+	assert(type != ARGTYPE_STRUCT);
+	return type;
+}
+#endif
+
 struct fetch_context *
 arch_fetch_arg_init(enum tof type, struct Process *proc,
 		    struct arg_type_info *ret_info)
@@ -118,6 +191,7 @@ arch_fetch_arg_init(enum tof type, struct Process *proc,
 		return NULL;
 	}
 
+#if _CALL_ELF != 2
 	/* Aggregates or unions of any length, and character strings
 	 * of length longer than 8 bytes, will be returned in a
 	 * storage buffer allocated by the caller. The caller will
@@ -125,6 +199,41 @@ arch_fetch_arg_init(enum tof type, struct Process *proc,
 	 * in r3, causing the first explicit argument to be passed in
 	 * r4.  */
 	context->ret_struct = ret_info->type == ARGTYPE_STRUCT;
+#else
+	/* There are two changes regarding structure return types:
+	* * homogeneous float/vector structs are returned
+	*   in (multiple) FP/vector registers,
+	*   instead of via implicit reference.
+	* * small structs (up to 16 bytes) are return
+	*   in one or two GPRs, instead of via implicit reference.
+
+	* Other structures (larger than 16 bytes, not homogeneous)
+	* are still returned via implicit reference (i.e. a pointer
+	* to memory where to return the struct being passed in r3).
+	* Of course, whether or not an implicit reference pointer
+	* is present will shift the remaining arguments,
+	* so you need to get this right for ELFv2 in order
+	* to get the arguments correct. */
+
+	struct struct_attributes struct_attr;
+	struct_attr.homogeneous = NOINIT;
+	struct_attr.nb_elements = 0;
+	size_t ret_size = 0;
+	context->ret_struct = 0;
+
+	if (ret_info->type == ARGTYPE_STRUCT) {
+		get_struct_attribut(ret_info, proc, &ret_size, &struct_attr);
+
+		if (((struct_attr.homogeneous == HOMOGENEOUS_NESTED_FLOAT) &&
+		   (struct_attr.nb_elements > 8)) ||
+		   (((struct_attr.homogeneous == HOMOGENEOUS) ||
+		     (struct_attr.homogeneous == HETEROGENEOUS)) &&
+		    (ret_size > 16)))
+
+		   context->ret_struct = 1;
+	}
+#endif
+
 	if (context->ret_struct)
 		context->greg++;
 
@@ -246,7 +355,7 @@ allocate_gpr(struct fetch_context *ctx, struct Process *proc,
 
 static int
 allocate_float(struct fetch_context *ctx, struct Process *proc,
-	       struct arg_type_info *info, struct value *valuep)
+		struct arg_type_info *info, struct value *valuep)
 {
 	int pool = proc->e_machine == EM_PPC64 ? 13 : 8;
 	if (ctx->freg <= pool) {
@@ -275,6 +384,58 @@ allocate_float(struct fetch_context *ctx, struct Process *proc,
 	return allocate_stack_slot(ctx, proc, info, valuep);
 }
 
+struct arg_type_info *
+arch_type_get_fp_equivalent(struct arg_type_info *info, struct Process *proc)
+{
+#if _CALL_ELF != 2
+	info = type_get_fp_equivalent(info);
+	return info;
+#else
+	struct struct_attributes struct_attr;
+	struct_attr.homogeneous = NOINIT;
+	struct_attr.nb_elements = 0;
+	size_t ret_size = 0;
+
+	if (info->type == ARGTYPE_STRUCT) {
+		enum arg_type elm_type =
+		   get_struct_attribut(info, proc, &ret_size, &struct_attr);
+
+		if ((struct_attr.nb_elements <= 8) &&
+		   ((struct_attr.homogeneous == HOMOGENEOUS) ||
+		    (struct_attr.homogeneous == HOMOGENEOUS_NESTED_FLOAT)) &&
+		   ((elm_type == ARGTYPE_FLOAT) ||
+		    (elm_type == ARGTYPE_DOUBLE)))
+			info = struct_attr.info;
+		    (elm_type == ARGTYPE_DOUBLE)))
+			info = struct_attr.info;
+		else
+			return NULL;
+	}
+
+	switch (info->type) {
+	case ARGTYPE_CHAR:
+	case ARGTYPE_SHORT:
+	case ARGTYPE_INT:
+	case ARGTYPE_LONG:
+	case ARGTYPE_UINT:
+	case ARGTYPE_ULONG:
+	case ARGTYPE_USHORT:
+	case ARGTYPE_VOID:
+	case ARGTYPE_ARRAY:
+	case ARGTYPE_POINTER:
+		return NULL;
+
+	case ARGTYPE_FLOAT:
+	case ARGTYPE_DOUBLE:
+		return info;
+
+	case ARGTYPE_STRUCT:
+		abort();
+	}
+	abort();
+#endif
+}
+
 static int
 allocate_argument(struct fetch_context *ctx, struct Process *proc,
 		  struct arg_type_info *info, struct value *valuep)
@@ -327,10 +488,32 @@ allocate_argument(struct fetch_context *ctx, struct Process *proc,
 	if (sz == (size_t)-1)
 		return -1;
 	size_t slots = (sz + width - 1) / width;  /* Round up.  */
+#if _CALL_ELF == 2
+	if (info->type == ARGTYPE_STRUCT) {
+		enum arg_type elm_type;
+		struct struct_attributes struct_attr;
+		struct_attr.homogeneous = NOINIT;
+		struct_attr.nb_elements = 0;
+		size_t dummy = 0;
+
+		elm_type =
+		   get_struct_attribut(info, proc, &dummy, &struct_attr);
+		if ((struct_attr.nb_elements <= 8) &&
+		   ((struct_attr.homogeneous == HOMOGENEOUS) ||
+		    (struct_attr.homogeneous == HOMOGENEOUS_NESTED_FLOAT)) &&
+		   (elm_type == ARGTYPE_FLOAT)) {
+			/* adjust sizes for float */
+			width = 4;
+			sz = width * struct_attr.nb_elements;
+			slots = (size_t)struct_attr.nb_elements;
+		}
+	}
+#endif
+
 	unsigned char *buf = value_reserve(valuep, slots * width);
 	if (buf == NULL)
 		return -1;
-	struct arg_type_info *long_info = type_get_simple(ARGTYPE_LONG);
+	struct arg_type_info *long_info = arch_type_get_simple(ARGTYPE_LONG,proc);
 
 	unsigned char *ptr = buf;
 	while (slots-- > 0) {
@@ -359,7 +542,11 @@ allocate_argument(struct fetch_context *ctx, struct Process *proc,
 		/* Bail out if we failed or if we are dealing with
 		 * FP-equivalent.  Those don't need the adjustments
 		 * made below.  */
+#if _CALL_ELF != 2
 		if (rc < 0 || fp_info != NULL)
+#else
+		if (rc < 0 )
+#endif
 			return rc;
 	}
 
diff --git a/ltrace.0.7.3-v1/sysdeps/linux-gnu/ppc/plt.c b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/plt.c
index 9097c27..2189cc3 100644
--- a/ltrace.0.7.3-v1/sysdeps/linux-gnu/ppc/plt.c
+++ b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/plt.c
@@ -113,7 +113,11 @@
  */
 
 #define PPC_PLT_STUB_SIZE 16
+#if _CALL_ELF != 2
 #define PPC64_PLT_STUB_SIZE 8 //xxx
+#else
+#define PPC64_PLT_STUB_SIZE 4 //xxx
+#endif
 
 static inline int
 host_powerpc64()
@@ -253,7 +257,11 @@ arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela)
 		 * that case we put brakpoints to PLT entries the same
 		 * as the PPC32 secure PLT case does.  */
 		assert(lte->arch.plt_stub_vma != 0);
+#if _CALL_ELF != 2
 		return lte->arch.plt_stub_vma + PPC64_PLT_STUB_SIZE * ndx;
+#else
+		return lte->arch.plt_stub_vma - 4  + PPC64_PLT_STUB_SIZE * ndx;
+#endif
 	}
 }
 
@@ -265,6 +273,7 @@ int
 arch_translate_address_dyn(struct Process *proc,
 			   arch_addr_t addr, arch_addr_t *ret)
 {
+#if _CALL_ELF != 2
 	if (proc->e_machine == EM_PPC64) {
 		uint64_t value;
 		if (read_target_8(proc, addr, &value) < 0) {
@@ -278,6 +287,7 @@ arch_translate_address_dyn(struct Process *proc,
 		*ret = (arch_addr_t)(uintptr_t)value;
 		return 0;
 	}
+#endif
 
 	*ret = addr;
 	return 0;
@@ -287,7 +297,8 @@ int
 arch_translate_address(struct ltelf *lte,
 		       arch_addr_t addr, arch_addr_t *ret)
 {
-	if (lte->ehdr.e_machine == EM_PPC64) {
+	if (lte->ehdr.e_machine == EM_PPC64
+	   && (lte->ehdr.e_flags & 3) != 2 ) {
 		/* XXX The double cast should be removed when
 		 * arch_addr_t becomes integral type.  */
 		GElf_Xword offset
@@ -433,6 +444,7 @@ int
 arch_elf_init(struct ltelf *lte, struct library *lib)
 {
 	if (lte->ehdr.e_machine == EM_PPC64
+	    && (lte->ehdr.e_flags & 3) != 2
 	    && load_opd_data(lte, lib) < 0)
 		return -1;
 
diff --git a/ltrace.0.7.3-v1/sysdeps/linux-gnu/ppc/trace.c b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/trace.c
index df53578..baf12ad 100644
--- a/ltrace.0.7.3-v1/sysdeps/linux-gnu/ppc/trace.c
+++ b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/trace.c
@@ -126,7 +126,9 @@ arch_atomic_singlestep(struct Process *proc, struct breakpoint *sbp,
 	int insn_count;
 	arch_addr_t addr = ip;
 	for (insn_count = 0; ; ++insn_count) {
+#if (!defined(__LITTLE_ENDIAN__)) || (_CALL_ELF == 2)
 		addr += 4;
+#endif
 		unsigned long l = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0);
 		if (l == (unsigned long)-1 && errno)
 			return -1;
From: Thierry Fauck <[email protected]>
Date: Thu, 20 Feb 2014 14:44:10 +0100
Subject: [PATCH 2/2] ltrace ppc64le ABIv2

	. For Ubuntu/Debian the ld64.so and libc.so may not
	have stub initialized when the libraries are dynamically loaded

 .../sysdeps/linux-gnu/ppc/plt.c                        | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/ltrace-0.7.3-v2/sysdeps/linux-gnu/ppc/plt.c b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/plt.c
index 2189cc3..8e03283 100644
--- a/ltrace-0.7.3-v2/sysdeps/linux-gnu/ppc/plt.c
+++ b/ltrace-0.7.3/sysdeps/linux-gnu/ppc/plt.c
@@ -585,7 +585,7 @@ read_plt_slot_value(struct Process *proc, GElf_Addr addr, GElf_Addr *valp)
 	uint64_t l;
 	/* XXX double cast.  */
 	if (read_target_8(proc, (arch_addr_t)(uintptr_t)addr, &l) < 0) {
-		fprintf(stderr, "ptrace .plt slot value @%#" PRIx64": %s\n",
+		debug(DEBUG_EVENT, "ptrace .plt slot value @%#" PRIx64": %s",
 			addr, strerror(errno));
 		return -1;
 	}
@@ -668,8 +668,18 @@ arch_elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
 	       || plt_slot_addr < lte->plt_addr + lte->plt_size);
 
 	GElf_Addr plt_slot_value;
-	if (read_plt_slot_value(proc, plt_slot_addr, &plt_slot_value) < 0)
+	if (read_plt_slot_value(proc, plt_slot_addr, &plt_slot_value) < 0) {
+#if _CALL_ELF != 2
 		return plt_fail;
+#else
+		/* With ABIv2, as we don't have .odp section,
+		   depending on how libc.so and ld.so are
+                   loaded stub area may not be initialized/dynamically
+		   loaded requiring the common process to do it
+                   usually making symbols latent */
+		return plt_default;
+#endif
+	}
 
 	char *name = strdup(a_name);
 	struct library_symbol *libsym = malloc(sizeof(*libsym));
@@ -862,9 +872,13 @@ ppc_plt_bp_continue(struct breakpoint *bp, struct Process *proc)
 			(struct process_stopping_handler *);
 
 	case PPC_DEFAULT:
+#if _CALL_ELF != 2
 		assert(proc->e_machine == EM_PPC);
 		assert(bp->libsym != NULL);
 		assert(bp->libsym->lib->arch.bss_plt_prelinked == 0);
+#else
+		/* ABIv2 uses plt and may set the flag */
+#endif
 		/* Fall through.  */
 
 	case PPC_PLT_UNRESOLVED:
_______________________________________________
Ltrace-devel mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/ltrace-devel

Reply via email to