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

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