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

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