Port-powerpc archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

semi-random crashes on some macppc hardware



Hello,

I've seen semi-random crashes ( often, but nowhere near always things
like sshd or makemandb would segfault during boot ) on some of my
macppc boxes for a while, for some reason mostly on a Powerbook Pismo
and not nearly as much on a beige G3. I finally had a closer look by
examining a bunch of .core files. Turns out on my Powerbook Pismo
( 500MHz ppc750, 1MB cache ) pretty much all the crashes happened in
PLT entries, and for no obvious reason.
To me that looks like insufficient instruction cache syncing when
writing the PLT entries in ld.elf_so, in order to test this I sprinkled
__syncicache() calls in a few suspicious-looking places in ppc_reloc.c.
I haven't seen any PLT-related crashes since.
The diff is attached, I'm sure it does more __syncicache()ing than
needed but so far I didn't have time to investigate further.

I dimly remember similar problems years ago.

have fun
Michael
Index: ppc_reloc.c
===================================================================
RCS file: /cvsroot/src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c,v
retrieving revision 1.53
diff -u -w -r1.53 ppc_reloc.c
--- ppc_reloc.c	25 Aug 2014 20:40:52 -0000	1.53
+++ ppc_reloc.c	12 May 2016 02:35:02 -0000
@@ -341,7 +341,7 @@
 			 * in _rtld_setup_pltgot() after all the entries have been
 			 * initialized.
 			 */
-			/* __syncicache(where - 3, 12); */
+			__syncicache(where - 3, 12);
 		}
 	}
 #endif /* !_LP64 */
@@ -353,6 +353,7 @@
 _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, int reloff, Elf_Addr *tp)
 {
 	Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset);
+	Elf_Word *w = where;
 	Elf_Addr value;
 	const Elf_Sym *def;
 	const Obj_Entry *defobj;
@@ -397,6 +398,7 @@
 		assert(where >= (Elf_Word *)obj->pltgot);
 		assert(where < (Elf_Word *)obj->pltgot + (obj->pltrelalim - obj->pltrela));
 		*where = value;
+		__syncicache(where, 4);
 	} else if (labs(distance) < 32*1024*1024) {	/* inside 32MB? */
 		/* b	value	# branch directly */
 		*where = 0x48000000 | (distance & 0x03fffffc);
@@ -437,7 +439,7 @@
 		/* b	pltcall	*/
 		distance = (Elf_Addr)pltcall - (Elf_Addr)where;
 		*where++ = 0x48000000 | (distance & 0x03fffffc);
-		__syncicache(where - 3, 12);
+		__syncicache(w, 12);
 	}
 #endif /* _LP64 */
 


Home | Main Index | Thread Index | Old Index