Blame SOURCES/ltrace-0.7.91-x86-plt_map.patch

f84355
From fba95ad936f1d8c1052259bae811f1fc07f9a215 Mon Sep 17 00:00:00 2001
f84355
From: Petr Machata <pmachata@redhat.com>
f84355
Date: Thu, 30 Oct 2014 01:48:17 +0100
f84355
Subject: [PATCH] Initialize the PLT slot map correctly on x86 and x86_64
f84355
f84355
The PLT slot map translates relocation numbers to PLT slot numbers,
f84355
but was actually initialized in the opposite direction.  Fix the way
f84355
it's initialized.  This bug can be seen on glibc in particular:
f84355
f84355
  $ ltrace -e free ls
f84355
  libc.so.6->free(0x5)           = <void>
f84355
  libc.so.6->free(0x78)          = <void>
f84355
  libc.so.6->free(0xc)           = <void>
f84355
  libc.so.6->free(0x308)         = <void>
f84355
f84355
Note the nonsense values passed to free.  The problem is that these
f84355
are not free calls at all, but malloc calls that are assigned to wrong
f84355
PLT slots due to above bug.
f84355
---
f84355
 sysdeps/linux-gnu/x86/plt.c | 38 +++++++++++++++++++++-----------------
f84355
 1 file changed, 21 insertions(+), 17 deletions(-)
f84355
f84355
diff --git a/sysdeps/linux-gnu/x86/plt.c b/sysdeps/linux-gnu/x86/plt.c
f84355
index c860af6..97f6c3e 100644
f84355
--- a/sysdeps/linux-gnu/x86/plt.c
f84355
+++ b/sysdeps/linux-gnu/x86/plt.c
f84355
@@ -77,6 +77,18 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
f84355
 {
f84355
 	VECT_INIT(&lte->arch.plt_map, unsigned int);
f84355
 
f84355
+	if (vect_reserve(&lte->arch.plt_map, vect_size(&lte->plt_relocs)) < 0) {
f84355
+	fail:
f84355
+		arch_elf_destroy(lte);
f84355
+		return -1;
f84355
+	}
f84355
+
f84355
+	{
f84355
+		unsigned int i, sz = vect_size(&lte->plt_relocs);
f84355
+		for (i = 0; i < sz; ++i)
f84355
+			vect_pushback (&lte->arch.plt_map, &i);
f84355
+	}
f84355
+
f84355
 	/* IRELATIVE slots may make the whole situation a fair deal
f84355
 	 * more complex.  On x86{,_64}, the PLT slots are not
f84355
 	 * presented in the order of the corresponding relocations,
f84355
@@ -114,43 +126,35 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
f84355
 	/* Here we scan the PLT table and initialize a map of
f84355
 	 * relocation->slot number in lte->arch.plt_map.  */
f84355
 
f84355
-	size_t i;
f84355
-	for (i = 0; i < vect_size(&lte->plt_relocs); ++i) {
f84355
+	unsigned int i, sz = vect_size(&lte->plt_relocs);
f84355
+	for (i = 0; i < sz; ++i) {
f84355
 
f84355
 		GElf_Addr offset = x86_plt_offset(i);
f84355
-		uint32_t reloc_arg = 0;
f84355
 
f84355
 		uint8_t byte;
f84355
 		if (elf_read_next_u8(lte->plt_data, &offset, &byte) < 0
f84355
 		    || byte != 0xff
f84355
 		    || elf_read_next_u8(lte->plt_data, &offset, &byte) < 0
f84355
 		    || (byte != 0xa3 && byte != 0x25))
f84355
-			goto next;
f84355
+			continue;
f84355
 
f84355
 		/* Skip immediate argument in the instruction.  */
f84355
 		offset += 4;
f84355
 
f84355
+		uint32_t reloc_arg;
f84355
 		if (elf_read_next_u8(lte->plt_data, &offset, &byte) < 0
f84355
 		    || byte != 0x68
f84355
 		    || elf_read_next_u32(lte->plt_data,
f84355
-					 &offset, &reloc_arg) < 0) {
f84355
-			reloc_arg = 0;
f84355
-			goto next;
f84355
-		}
f84355
+					 &offset, &reloc_arg) < 0)
f84355
+			continue;
f84355
 
f84355
 		if (lte->ehdr.e_machine == EM_386) {
f84355
-			if (reloc_arg % 8 != 0) {
f84355
-				reloc_arg = 0;
f84355
-				goto next;
f84355
-			}
f84355
+			if (reloc_arg % 8 != 0)
f84355
+				continue;
f84355
 			reloc_arg /= 8;
f84355
 		}
f84355
 
f84355
-	next:
f84355
-		if (VECT_PUSHBACK(&lte->arch.plt_map, &reloc_arg) < 0) {
f84355
-			arch_elf_destroy(lte);
f84355
-			return -1;
f84355
-		}
f84355
+		*VECT_ELEMENT(&lte->arch.plt_map, unsigned int, reloc_arg) = i;
f84355
 	}
f84355
 
f84355
 	return 0;
f84355
-- 
f84355
2.1.0
f84355