Blame SOURCES/ltrace-0.7.91-cet.patch

8d9cfe
diff -rup a/ltrace-elf.c b/ltrace-elf.c
8d9cfe
--- a/ltrace-elf.c	2019-02-28 17:32:49.873659818 -0500
8d9cfe
+++ b/ltrace-elf.c	2019-02-28 17:36:32.426779439 -0500
8d9cfe
@@ -639,7 +639,21 @@ ltelf_read_elf(struct ltelf *lte, const
8d9cfe
 			}
8d9cfe
 		} else if (shdr.sh_type == SHT_PROGBITS
8d9cfe
 			   || shdr.sh_type == SHT_NOBITS) {
8d9cfe
-			if (strcmp(name, ".plt") == 0) {
8d9cfe
+			if (strcmp(name, ".plt") == 0
8d9cfe
+			    && lte->second_plt_seen == 0) {
8d9cfe
+				lte->plt_addr = shdr.sh_addr;
8d9cfe
+				lte->plt_size = shdr.sh_size;
8d9cfe
+				lte->plt_data = elf_loaddata(scn, &shdr);
8d9cfe
+				if (lte->plt_data == NULL)
8d9cfe
+					fprintf(stderr,
8d9cfe
+						"Can't load .plt data\n");
8d9cfe
+				lte->plt_flags = shdr.sh_flags;
8d9cfe
+			}
8d9cfe
+			/* An Intel CET binary has two PLTs; the
8d9cfe
+			   initial PLTGOT points to the second
8d9cfe
+			   one.  */
8d9cfe
+			else if (strcmp(name, ".plt.sec") == 0) {
8d9cfe
+				lte->second_plt_seen = 1;
8d9cfe
 				lte->plt_addr = shdr.sh_addr;
8d9cfe
 				lte->plt_size = shdr.sh_size;
8d9cfe
 				lte->plt_data = elf_loaddata(scn, &shdr);
8d9cfe
diff -rup a/ltrace-elf.h b/ltrace-elf.h
8d9cfe
--- a/ltrace-elf.h	2019-02-28 17:32:49.874660328 -0500
8d9cfe
+++ b/ltrace-elf.h	2019-02-28 17:36:32.428779868 -0500
8d9cfe
@@ -45,6 +45,7 @@ struct ltelf {
8d9cfe
 	Elf_Data *dynsym;
8d9cfe
 	size_t dynsym_count;
8d9cfe
 	const char *dynstr;
8d9cfe
+	int second_plt_seen;
8d9cfe
 	GElf_Addr plt_addr;
8d9cfe
 	GElf_Word plt_flags;
8d9cfe
 	size_t plt_size;
8d9cfe
diff -rup a/sysdeps/linux-gnu/x86/plt.c b/sysdeps/linux-gnu/x86/plt.c
8d9cfe
--- a/sysdeps/linux-gnu/x86/plt.c	2019-02-28 17:32:49.991720041 -0500
8d9cfe
+++ b/sysdeps/linux-gnu/x86/plt.c	2019-02-28 17:36:32.429780083 -0500
8d9cfe
@@ -28,18 +28,18 @@
8d9cfe
 #include "trace.h"
8d9cfe
 
8d9cfe
 static GElf_Addr
8d9cfe
-x86_plt_offset(uint32_t i)
8d9cfe
+x86_plt_offset(struct ltelf *lte, uint32_t i)
8d9cfe
 {
8d9cfe
 	/* Skip the first PLT entry, which contains a stub to call the
8d9cfe
 	 * resolver.  */
8d9cfe
-	return (i + 1) * 16;
8d9cfe
+	return (i + (lte->second_plt_seen ? 0 : 1)) * 16;
8d9cfe
 }
8d9cfe
 
8d9cfe
 GElf_Addr
8d9cfe
 arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela)
8d9cfe
 {
8d9cfe
 	uint32_t i = *VECT_ELEMENT(&lte->arch.plt_map, uint32_t, ndx);
8d9cfe
-	return x86_plt_offset(i) + lte->plt_addr;
8d9cfe
+	return x86_plt_offset(lte, i) + lte->plt_addr;
8d9cfe
 }
8d9cfe
 
8d9cfe
 void *
8d9cfe
@@ -116,6 +116,13 @@ arch_elf_init(struct ltelf *lte, struct
8d9cfe
 	 *	 400426:   68 00 00 00 00          pushq  $0x0
8d9cfe
 	 *	 40042b:   e9 e0 ff ff ff          jmpq   400410 <_init+0x18>
8d9cfe
 	 *
8d9cfe
+	 * For CET binaries it is the following:
8d9cfe
+	 *
8d9cfe
+	 *	13d0:       f3 0f 1e fa             endbr64 
8d9cfe
+	 *	13d4:       68 27 00 00 00          pushq  $0x27  <-- index
8d9cfe
+	 *	13d9:       f2 e9 71 fd ff ff       bnd jmpq 1150 <.plt>
8d9cfe
+	 *	13df:       90                      nop
8d9cfe
+	 *
8d9cfe
          * On i386, the argument to push is an offset of relocation to
8d9cfe
 	 * use.  The first PLT slot has an offset of 0x0, the second
8d9cfe
 	 * 0x8, etc.  On x86_64, it's directly the index that we are
8d9cfe
@@ -128,11 +135,33 @@ arch_elf_init(struct ltelf *lte, struct
8d9cfe
 	unsigned int i, sz = vect_size(&lte->plt_relocs);
8d9cfe
 	for (i = 0; i < sz; ++i) {
8d9cfe
 
8d9cfe
-		GElf_Addr offset = x86_plt_offset(i);
8d9cfe
+		GElf_Addr offset = x86_plt_offset(lte, i);
8d9cfe
+		uint32_t reloc_arg;
8d9cfe
 
8d9cfe
 		uint8_t byte;
8d9cfe
-		if (elf_read_next_u8(lte->plt_data, &offset, &byte) < 0
8d9cfe
-		    || byte != 0xff
8d9cfe
+		if (elf_read_next_u8(lte->plt_data, &offset, &byte) < 0)
8d9cfe
+		  continue;
8d9cfe
+
8d9cfe
+
8d9cfe
+		if (byte == 0xf3
8d9cfe
+		    && elf_read_next_u8(lte->plt_data, &offset, &byte) >= 0
8d9cfe
+		    && byte == 0x0f
8d9cfe
+		    && elf_read_next_u8(lte->plt_data, &offset, &byte) >= 0
8d9cfe
+		    && byte == 0x1e
8d9cfe
+		    && elf_read_next_u8(lte->plt_data, &offset, &byte) >= 0
8d9cfe
+		    && byte == 0xfa
8d9cfe
+		    && elf_read_next_u8(lte->plt_data, &offset, &byte) >= 0
8d9cfe
+		    && byte == 0x68
8d9cfe
+		    && elf_read_next_u32(lte->plt_data,
8d9cfe
+					 &offset, &reloc_arg) >= 0)
8d9cfe
+		  {
8d9cfe
+		    /* CET */
8d9cfe
+		    fprintf(stderr, "%d: reloc_arg is %lx\n", i, (long)reloc_arg);
8d9cfe
+		    *VECT_ELEMENT(&lte->arch.plt_map, unsigned int, reloc_arg) = i;
8d9cfe
+		    continue;
8d9cfe
+		  }
8d9cfe
+
8d9cfe
+		if (byte != 0xff
8d9cfe
 		    || elf_read_next_u8(lte->plt_data, &offset, &byte) < 0
8d9cfe
 		    || (byte != 0xa3 && byte != 0x25))
8d9cfe
 			continue;
8d9cfe
@@ -140,7 +169,6 @@ arch_elf_init(struct ltelf *lte, struct
8d9cfe
 		/* Skip immediate argument in the instruction.  */
8d9cfe
 		offset += 4;
8d9cfe
 
8d9cfe
-		uint32_t reloc_arg;
8d9cfe
 		if (elf_read_next_u8(lte->plt_data, &offset, &byte) < 0
8d9cfe
 		    || byte != 0x68
8d9cfe
 		    || elf_read_next_u32(lte->plt_data,