Module Name:    src
Committed By:   rin
Date:           Fri May  6 04:49:13 UTC 2022

Modified Files:
        src/lib/libc/gmon: gmon.c

Log Message:
PR lib/56395
PR toolchain/56771

Fix profiling on CPUs that do not support unaligned memory access;
Allocate objects (referenced from struct gmonparam) with proper
alignments.

For monstartup(), objects are allocated on heap. Break is not
guaranteed to be aligned at all, unlike stack pointer.

For _m_gmon_alloc(), objects are allocated on anonymous memory.
p->tos is not aligned properly in general.

This fixes quasi-random crashes for *_profile tests, at least on
SH-4 and PowerPC 403 [1]. Also, no regression is observed for
others as far as I can see.

This change does not cause any ABI breakage, as long as application
uses proper pointers; use p->tos instead of evil pointer arithmetic
like (struct tostruct *)((char *)p->froms + p->fromssize) [2].

[1] Timeout should be increased for some tests. "pic" variants
still fail as expected. Dynamically-linked binaries also crash in
rtld for SH-4, but this seems different problem...

[2] This example did not work even before, since the order of
froms[] and tos[] is reversed depending on which of monstartup() or
_m_gmon_alloc() is used for allocation.


To generate a diff of this commit:
cvs rdiff -u -r1.36 -r1.37 src/lib/libc/gmon/gmon.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libc/gmon/gmon.c
diff -u src/lib/libc/gmon/gmon.c:1.36 src/lib/libc/gmon/gmon.c:1.37
--- src/lib/libc/gmon/gmon.c:1.36	Sat Jul  3 14:08:55 2021
+++ src/lib/libc/gmon/gmon.c	Fri May  6 04:49:13 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: gmon.c,v 1.36 2021/07/03 14:08:55 christos Exp $	*/
+/*	$NetBSD: gmon.c,v 1.37 2022/05/06 04:49:13 rin Exp $	*/
 
 /*
  * Copyright (c) 2003, 2004 Wasabi Systems, Inc.
@@ -69,7 +69,7 @@
 #if 0
 static char sccsid[] = "@(#)gmon.c	8.1 (Berkeley) 6/4/93";
 #else
-__RCSID("$NetBSD: gmon.c,v 1.36 2021/07/03 14:08:55 christos Exp $");
+__RCSID("$NetBSD: gmon.c,v 1.37 2022/05/06 04:49:13 rin Exp $");
 #endif
 #endif
 
@@ -141,21 +141,25 @@ monstartup(u_long lowpc, u_long highpc)
 		p->tolimit = MAXARCS;
 	p->tossize = p->tolimit * sizeof(struct tostruct);
 
-	cp = sbrk((intptr_t)(p->kcountsize + p->fromssize + p->tossize));
-	if (cp == (char *)-1) {
+	cp = sbrk((intptr_t)0);
+
+#define	GMON_ALLOC(buf, ptr, size)					\
+    do {								\
+	(buf) = (void *)roundup((uintptr_t)(buf), __alignof(*(ptr)));	\
+	(ptr) = (void *)(buf);						\
+	(buf) += (size);						\
+    } while (0)
+
+	GMON_ALLOC(cp, p->kcount, p->kcountsize);
+	GMON_ALLOC(cp, p->froms, p->fromssize);
+	GMON_ALLOC(cp, p->tos, p->tossize);
+
+	if (brk(cp)) {
 		warnx("%s: out of memory", __func__);
 		return;
 	}
-#ifdef notdef
-	(void)memset(cp, 0, p->kcountsize + p->fromssize + p->tossize);
-#endif
-	p->tos = (struct tostruct *)(void *)cp;
-	cp += (size_t)p->tossize;
-	p->kcount = (u_short *)(void *)cp;
-	cp += (size_t)p->kcountsize;
-	p->froms = (u_short *)(void *)cp;
+	__minbrk = cp;
 
-	__minbrk = sbrk((intptr_t)0);
 	p->tos[0].link = 0;
 
 	o = p->highpc - p->lowpc;
@@ -226,17 +230,22 @@ _m_gmon_alloc(void)
 	} else {
 		mutex_unlock(&_gmonlock);
 		cp = mmap(NULL,
-		    (size_t)(sizeof (struct gmonparam) + 
-			_gmonparam.fromssize + _gmonparam.tossize),
+		    (size_t)(__alignof(*p) + sizeof(*p) +
+			__alignof(*_gmonparam.froms) + _gmonparam.fromssize +
+			__alignof(*_gmonparam.tos) + _gmonparam.tossize),
 		    PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, (off_t)0);
-		p = (void *)cp;
+
+		GMON_ALLOC(cp, p, sizeof(*p));
 		*p = _gmonparam;
 		p->state = GMON_PROF_ON;
 		p->kcount = NULL;
-		cp += sizeof (struct gmonparam);
-		memset(cp, 0, (size_t)(p->fromssize + p->tossize));
-		p->froms = (u_short *)(void *)cp;
-		p->tos = (struct tostruct *)(void *)(cp + p->fromssize);
+
+		GMON_ALLOC(cp, p->froms, p->fromssize);
+		memset(p->froms, 0, p->fromssize);
+
+		GMON_ALLOC(cp, p->tos, p->tossize);
+		memset(p->tos, 0, p->tossize);
+
 		mutex_lock(&_gmonlock);
 		p->kcount = (u_short *)(void *)_gmoninuse;
 		_gmoninuse = p;

Reply via email to