codonell / rpms / ltrace

Forked from rpms/ltrace 4 years ago
Clone
Petr Machata 5f8efb0
diff --git a/sysdeps/linux-gnu/ppc/plt.c b/sysdeps/linux-gnu/ppc/plt.c
Petr Machata 5f8efb0
index 45ed7fb..5f81889 100644
Petr Machata 5f8efb0
--- a/sysdeps/linux-gnu/ppc/plt.c
Petr Machata 5f8efb0
+++ b/sysdeps/linux-gnu/ppc/plt.c
Petr Machata 5f8efb0
@@ -274,14 +274,15 @@ arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela)
Petr Machata 5f8efb0
 
Petr Machata 5f8efb0
 		assert(rela->r_addend != 0);
Petr Machata 5f8efb0
 		/* XXX double cast */
Petr Machata 5f8efb0
-		arch_addr_t res_addr = (arch_addr_t) (uintptr_t) rela->r_addend;
Petr Machata 5f8efb0
+		arch_addr_t res_addr
Petr Machata 5f8efb0
+		  = (arch_addr_t) (uintptr_t) (rela->r_addend + lte->bias);
Petr Machata 5f8efb0
 		if (arch_translate_address(lte, res_addr, &res_addr) < 0) {
Petr Machata 5f8efb0
 			fprintf(stderr, "Couldn't OPD-translate IRELATIVE "
Petr Machata 5f8efb0
 				"resolver address.\n");
Petr Machata 5f8efb0
 			return 0;
Petr Machata 5f8efb0
 		}
Petr Machata 5f8efb0
 		/* XXX double cast */
Petr Machata 5f8efb0
-		return (GElf_Addr) (uintptr_t) res_addr;
Petr Machata 5f8efb0
+		return (GElf_Addr) (uintptr_t) (res_addr - lte->bias);
Petr Machata 5f8efb0
 
Petr Machata 5f8efb0
 	} else {
Petr Machata 5f8efb0
 		/* We put brakpoints to PLT entries the same as the
Petr Machata 5f8efb0
@@ -453,7 +454,7 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
Petr Machata 5f8efb0
 #ifndef EF_PPC64_ABI
Petr Machata 5f8efb0
 	assert (! (lte->ehdr.e_flags & 3 ) == 2)
Petr Machata 5f8efb0
 #else
Petr Machata 5f8efb0
-	lte->arch.elfv2_abi=((lte->ehdr.e_flags & EF_PPC64_ABI) == 2) ;
Petr Machata 5f8efb0
+	lte->arch.elfv2_abi = ((lte->ehdr.e_flags & EF_PPC64_ABI) == 2);
Petr Machata 5f8efb0
 #endif
Petr Machata 5f8efb0
 
Petr Machata 5f8efb0
 	if (lte->ehdr.e_machine == EM_PPC64
Petr Machata 5f8efb0
@@ -827,15 +828,15 @@ arch_elf_add_plt_entry(struct process *proc, struct ltelf *lte,
Petr Machata 5f8efb0
 	assert(plt_slot_addr >= lte->plt_addr
Petr Machata 5f8efb0
 	       || plt_slot_addr < lte->plt_addr + lte->plt_size);
Petr Machata 5f8efb0
 
Petr Machata 5f8efb0
+	plt_entry_addr += lte->bias;
Petr Machata 5f8efb0
+	plt_slot_addr += lte->bias;
Petr Machata 5f8efb0
+
Petr Machata 5f8efb0
 	/* Should avoid to do read if dynamic linker hasn't run yet
Petr Machata 5f8efb0
 	 * or allow -1 a valid return code.  */
Petr Machata 5f8efb0
 	GElf_Addr plt_slot_value;
Petr Machata 5f8efb0
-	if (read_plt_slot_value(proc, plt_slot_addr, &plt_slot_value) < 0) {
Petr Machata 5f8efb0
-		if (!lte->arch.elfv2_abi)
Petr Machata 5f8efb0
-			goto fail;
Petr Machata 5f8efb0
-		else
Petr Machata 5f8efb0
-			return PPC_PLT_UNRESOLVED;
Petr Machata 5f8efb0
-	}
Petr Machata 5f8efb0
+	int rc = read_plt_slot_value(proc, plt_slot_addr, &plt_slot_value);
Petr Machata 5f8efb0
+	if (rc < 0 && !lte->arch.elfv2_abi)
Petr Machata 5f8efb0
+		goto fail;
Petr Machata 5f8efb0
 
Petr Machata 5f8efb0
 	struct library_symbol *libsym = malloc(sizeof(*libsym));
Petr Machata 5f8efb0
 	if (libsym == NULL) {
Petr Machata 5f8efb0
@@ -854,8 +855,9 @@ arch_elf_add_plt_entry(struct process *proc, struct ltelf *lte,
Petr Machata 5f8efb0
 		goto fail2;
Petr Machata 5f8efb0
 	libsym->arch.plt_slot_addr = plt_slot_addr;
Petr Machata 5f8efb0
 
Petr Machata 5f8efb0
-	if (! is_irelative
Petr Machata 5f8efb0
-	    && (plt_slot_value == plt_entry_addr || plt_slot_value == 0)) {
Petr Machata 5f8efb0
+	if (rc < 0 || (! is_irelative
Petr Machata 5f8efb0
+		       && (plt_slot_value == plt_entry_addr
Petr Machata 5f8efb0
+			   || plt_slot_value == 0))) {
Petr Machata 5f8efb0
 		libsym->arch.type = PPC_PLT_UNRESOLVED;
Petr Machata 5f8efb0
 		libsym->arch.resolved_value = plt_entry_addr;
Petr Machata 5f8efb0
 	} else {
Petr Machata 5f8efb0
@@ -1166,8 +1168,8 @@ ppc_plt_bp_install(struct breakpoint *bp, struct process *proc)
Petr Machata 5f8efb0
 				libsym->arch.resolved_value = plt_entry_addr;
Petr Machata 5f8efb0
 			}
Petr Machata 5f8efb0
 		} else {
Petr Machata 5f8efb0
-			fprintf(stderr, "Couldn't unresolve %s@%p.  Not tracing"
Petr Machata 5f8efb0
-				" this symbol.\n",
Petr Machata 5f8efb0
+			fprintf(stderr, "Couldn't unresolve %s@%p.  Will not"
Petr Machata 5f8efb0
+				" trace this symbol.\n",
Petr Machata 5f8efb0
 				breakpoint_name(bp), bp->addr);
Petr Machata 5f8efb0
 			proc_remove_breakpoint(proc, bp);
Petr Machata 5f8efb0
 		}
Petr Machata 5f8efb0
@@ -1222,6 +1224,14 @@ arch_library_symbol_clone(struct library_symbol *retp,
Petr Machata 5f8efb0
 			  struct library_symbol *libsym)
Petr Machata 5f8efb0
 {
Petr Machata 5f8efb0
 	retp->arch = libsym->arch;
Petr Machata 5f8efb0
+	if (libsym->arch.type == PPC_PLT_NEED_UNRESOLVE) {
Petr Machata 5f8efb0
+		assert(libsym->arch.data->self == libsym->arch.data);
Petr Machata 5f8efb0
+		retp->arch.data = malloc(sizeof *retp->arch.data);
Petr Machata 5f8efb0
+		if (retp->arch.data == NULL)
Petr Machata 5f8efb0
+			return -1;
Petr Machata 5f8efb0
+		*retp->arch.data = *libsym->arch.data;
Petr Machata 5f8efb0
+		retp->arch.data->self = retp->arch.data;
Petr Machata 5f8efb0
+	}
Petr Machata 5f8efb0
 	return 0;
Petr Machata 5f8efb0
 }
Petr Machata 5f8efb0