File ltrace-ppc64le_git14.patch of Package ltrace

--- backend.h.ori
+++ backend.h 
@@ -294,8 +294,8 @@ enum plt_status {
 	plt_default,
 };
 
-/* The following callback has to be implemented in backend if arch.h
- * defines ARCH_HAVE_ADD_PLT_ENTRY.
+/* The following callback has to be implemented in OS backend if os.h
+ * defines OS_HAVE_ADD_PLT_ENTRY.
  *
  * This is called for every PLT relocation R in ELF file LTE, that
  * ltrace is about to add to a library constructed in process PROC.
@@ -306,11 +306,18 @@ enum plt_status {
  * calling arch_plt_sym_val, and symbol is allocated.  If plt_ok or
  * plt_default are returned, the chain of symbols passed back in RET
  * is added to library under construction.  */
+enum plt_status os_elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
+				     const char *name, GElf_Rela *rela,
+				     size_t i, struct library_symbol **ret);
+
+/* Like os_elf_add_plt_entry, but tied to ARCH_HAVE_ADD_PLT_ENTRY in
+ * arch.h.  The arch callback is called first.  If it returns
+ * plt_default, the os callback is called next.  */
 enum plt_status arch_elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
 				       const char *name, GElf_Rela *rela,
 				       size_t i, struct library_symbol **ret);
 
-/* The following callback has to be implemented in backend if arch.h
+/* The following callback has to be implemented in OS backend if os.h
  * defines OS_HAVE_ADD_FUNC_ENTRY.
  *
  * This is called for every symbol in ltrace is about to add to the
@@ -327,6 +334,14 @@ enum plt_status os_elf_add_func_entry(struct Process *proc, struct ltelf *lte,
 				      arch_addr_t addr, const char *name,
 				      struct library_symbol **ret);
 
+/* Like os_elf_add_func_entry, but tied to ARCH_HAVE_ADD_FUNC_ENTRY in
+ * arch.h.  The arch callback is called first.  If it returns
+ * plt_default, the os callback is called next.  */
+enum plt_status arch_elf_add_func_entry(struct Process *proc, struct ltelf *lte,
+					const GElf_Sym *sym,
+					arch_addr_t addr, const char *name,
+					struct library_symbol **ret);
+
 /* This callback needs to be implemented if arch.h defines
  * ARCH_HAVE_DYNLINK_DONE.  It is called after the dynamic linker is
  * done with the process startup.  */
--- ltrace-elf.c.ori
+++ ltrace-elf.c
@@ -36,6 +36,7 @@
 #include <gelf.h>
 #include <inttypes.h>
 #include <search.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -63,41 +64,15 @@ arch_elf_destroy(struct ltelf *lte)
 }
 #endif
 
-int
-default_elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
-			  const char *a_name, GElf_Rela *rela, size_t ndx,
-			  struct library_symbol **ret)
+#ifndef OS_HAVE_ADD_PLT_ENTRY
+enum plt_status
+os_elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
+		     const char *a_name, GElf_Rela *rela, size_t ndx,
+		     struct library_symbol **ret)
 {
-	char *name = strdup(a_name);
-	if (name == NULL) {
-	fail_message:
-		fprintf(stderr, "Couldn't create symbol for PLT entry: %s\n",
-			strerror(errno));
-	fail:
-		free(name);
-		return -1;
-	}
-
-	GElf_Addr addr = arch_plt_sym_val(lte, ndx, rela);
-
-	struct library_symbol *libsym = malloc(sizeof(*libsym));
-	if (libsym == NULL)
-		goto fail_message;
-
-	/* XXX The double cast should be removed when
-	 * arch_addr_t becomes integral type.  */
-	arch_addr_t taddr = (arch_addr_t)
-		(uintptr_t)(addr + lte->bias);
-
-	if (library_symbol_init(libsym, taddr, name, 1, LS_TOPLT_EXEC) < 0) {
-		free(libsym);
-		goto fail;
-	}
-
-	libsym->next = *ret;
-	*ret = libsym;
-	return 0;
+	return plt_default;
 }
+#endif
 
 #ifndef ARCH_HAVE_ADD_PLT_ENTRY
 enum plt_status
@@ -125,6 +100,17 @@ os_elf_add_func_entry(struct Process *proc, struct ltelf *lte,
 }
 #endif
 
+#ifndef ARCH_HAVE_ADD_FUNC_ENTRY
+enum plt_status
+arch_elf_add_func_entry(struct Process *proc, struct ltelf *lte,
+			const GElf_Sym *sym,
+			arch_addr_t addr, const char *name,
+			struct library_symbol **ret)
+{
+	return plt_default;
+}
+#endif
+
 Elf_Data *
 elf_loaddata(Elf_Scn *scn, GElf_Shdr *shdr)
 {
@@ -645,6 +631,67 @@ arch_get_sym_info(struct ltelf *lte, const char *filename,
 }
 #endif
 
+int
+default_elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
+			  const char *a_name, GElf_Rela *rela, size_t ndx,
+			  struct library_symbol **ret)
+{
+	char *name = strdup(a_name);
+	if (name == NULL) {
+	fail_message:
+		fprintf(stderr, "Couldn't create symbol for PLT entry: %s\n",
+			strerror(errno));
+	fail:
+		free(name);
+		return -1;
+	}
+
+	GElf_Addr addr = arch_plt_sym_val(lte, ndx, rela);
+
+	struct library_symbol *libsym = malloc(sizeof(*libsym));
+	if (libsym == NULL)
+		goto fail_message;
+
+	/* XXX The double cast should be removed when
+	 * arch_addr_t becomes integral type.  */
+	arch_addr_t taddr = (arch_addr_t)
+		(uintptr_t)(addr + lte->bias);
+
+	if (library_symbol_init(libsym, taddr, name, 1, LS_TOPLT_EXEC) < 0) {
+		free(libsym);
+		goto fail;
+	}
+
+	libsym->next = *ret;
+	*ret = libsym;
+	return 0;
+}
+
+int
+elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
+		  const char *name, GElf_Rela *rela, size_t idx,
+		  struct library_symbol **ret)
+{
+	enum plt_status plts
+		= arch_elf_add_plt_entry(proc, lte, name, rela, idx, ret);
+
+	if (plts == plt_default)
+		plts = os_elf_add_plt_entry(proc, lte, name, rela, idx, ret);
+
+	switch (plts) {
+	case plt_default:
+		return default_elf_add_plt_entry(proc, lte, name,
+						 rela, idx, ret);
+	case plt_fail:
+		return -1;
+	case plt_ok:
+		return 0;
+	}
+
+	assert(! "Invalid return from X_elf_add_plt_entry!");
+	abort();
+}
+
 static void
 mark_chain_latent(struct library_symbol *libsym)
 {
@@ -672,23 +719,13 @@ filter_symbol_chain(struct filter *filter,
 	}
 }
 
-static void
-delete_symbol_chain(struct library_symbol *libsym)
-{
-	while (libsym != NULL) {
-		struct library_symbol *tmp = libsym->next;
-		library_symbol_destroy(libsym);
-		free(libsym);
-		libsym = tmp;
-	}
-}
-
 static int
 populate_plt(struct Process *proc, const char *filename,
-	     struct ltelf *lte, struct library *lib,
-	     int latent_plts)
+	     struct ltelf *lte, struct library *lib)
 {
-	size_t count = vect_size(&lte->plt_relocs);
+	const bool latent_plts = options.export_filter != NULL;
+	const size_t count = vect_size(&lte->plt_relocs);
+
 	size_t i;
 	for (i = 0; i < count; ++i) {
 		GElf_Rela *rela = VECT_ELEMENT(&lte->plt_relocs, GElf_Rela, i);
@@ -698,45 +735,43 @@ populate_plt(struct Process *proc, const char *filename,
 			continue; /* Skip this entry.  */
 
 		char const *name = lte->dynstr + sym.st_name;
-
 		int matched = filter_matches_symbol(options.plt_filter,
 						    name, lib);
 
 		struct library_symbol *libsym = NULL;
-		switch (arch_elf_add_plt_entry(proc, lte, name,
-					       rela, i, &libsym)) {
-		case plt_fail:
+		if (elf_add_plt_entry(proc, lte, name, rela, i, &libsym) < 0)
 			return -1;
 
-		case plt_default:
-			/* Add default entry to the beginning of LIBSYM.  */
-			if (default_elf_add_plt_entry(proc, lte, name,
-						      rela, i, &libsym) < 0)
-				return -1;
-			/* fall-through */
-		case plt_ok:
-			/* If we didn't match the PLT entry up there,
-			 * filter the chain to only include the
-			 * matching symbols (but include all if we are
-			 * adding latent symbols).  This is to allow
-			 * arch_elf_add_plt_entry to override the PLT
-			 * symbol's name.  */
-			if (!matched && !latent_plts)
-				filter_symbol_chain(options.plt_filter,
-						    &libsym, lib);
-			if (libsym != NULL) {
-				/* If we are adding those symbols just
-				 * for tracing exports, mark them all
-				 * latent.  */
-				if (!matched && latent_plts)
-					mark_chain_latent(libsym);
-				library_add_symbol(lib, libsym);
-			}
+		/* If we didn't match the PLT entry, filter the chain
+		 * to only include the matching symbols (but include
+		 * all if we are adding latent symbols) to allow
+		 * backends to override the PLT symbol's name.  */
+
+		if (! matched && ! latent_plts)
+			filter_symbol_chain(options.plt_filter, &libsym, lib);
+
+		if (libsym != NULL) {
+			/* If we are adding those symbols just for
+			 * tracing exports, mark them all latent.  */
+			if (! matched && latent_plts)
+				mark_chain_latent(libsym);
+			library_add_symbol(lib, libsym);
 		}
 	}
 	return 0;
 }
 
+static void
+delete_symbol_chain(struct library_symbol *libsym)
+{
+	while (libsym != NULL) {
+		struct library_symbol *tmp = libsym->next;
+		library_symbol_destroy(libsym);
+		free(libsym);
+		libsym = tmp;
+	}
+}
+
 /* When -x rules result in request to trace several aliases, we only
  * want to add such symbol once.  The only way that those symbols
  * differ in is their name, e.g. in glibc you have __GI___libc_free,
@@ -872,8 +909,14 @@ populate_this_symtab(struct Process *proc, const char *filename,
 		}
 
 		struct library_symbol *libsym = NULL;
-		switch (os_elf_add_func_entry(proc, lte, &sym,
-					      naddr, full_name, &libsym)) {
+		enum plt_status plts
+			= arch_elf_add_func_entry(proc, lte, &sym,
+						  naddr, full_name, &libsym);
+		if (plts == plt_default)
+			plts = os_elf_add_func_entry(proc, lte, &sym,
+						     naddr, full_name, &libsym);
+
+		switch (plts) {
 		case plt_default:;
 			/* Put the default symbol to the chain.  */
 			struct library_symbol *tmp = malloc(sizeof *tmp);
@@ -924,6 +967,7 @@ populate_this_symtab(struct Process *proc, const char *filename,
 				unique->libsym = tmp;
 				unique->addr = tmp->enter_addr;
 				tmp = tmp->next;
+				unique->libsym->next = NULL;
 			} else {
 				if (strlen(tmp->name)
 				    < strlen(unique->libsym->name)) {
@@ -1108,8 +1152,7 @@ read_module(struct library *lib, struct Process *proc,
 
 	int plts = filter_matches_library(options.plt_filter, lib);
 	if ((plts || options.export_filter != NULL)
-	    && populate_plt(proc, filename, &lte, lib,
-			    options.export_filter != NULL) < 0)
+	    && populate_plt(proc, filename, &lte, lib) < 0)
 		goto fail;
 
 	int exports = filter_matches_library(options.export_filter, lib);
--- ltrace-elf.h.ori
+++ ltrace-elf.h
@@ -83,6 +83,22 @@ int ltelf_read_library(struct library *lib, struct Process *proc,
  * point address is stored to *ENTRYP.  */
 struct library *ltelf_read_main_binary(struct Process *proc, const char *path);
 
+/* This is called for every PLT relocation R in ELF file LTE, that
+ * ltrace is about to add to a library constructed in process PROC.
+ * The corresponding PLT entry is for symbol called NAME, and it's
+ * I-th relocation in the file.  *RET shall be initialized and
+ * symbol(s) corresponding to the given PLT entry will be added to the
+ * front.  Returns 0 for success, or a negative value for failures.
+ *
+ * This calls os_elf_add_plt_entry and arch_elf_add_plt_entry in the
+ * background (see backend.h for documentation).  The arch callback is
+ * called first.  If it returns plt_default, the os callback is called
+ * next.  If that returns plt_default, default_elf_add_plt_entry is
+ * called.  */
+int elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
+		      const char *name, GElf_Rela *rela, size_t idx,
+		      struct library_symbol **ret);
+
 /* Create a default PLT entry.  This can be used instead (or in
  * addition to) returning plt_default from arch_elf_add_plt_entry.
  * RET shall be initialized, the created symbol will be added to the