Source-Changes-HG archive

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

[src/trunk]: src/lib/libc/gmon PR lib/56395



details:   https://anonhg.NetBSD.org/src/rev/ebf4f0c26130
branches:  trunk
changeset: 365959:ebf4f0c26130
user:      rin <rin%NetBSD.org@localhost>
date:      Fri May 06 04:49:13 2022 +0000

description:
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.

diffstat:

 lib/libc/gmon/gmon.c |  49 +++++++++++++++++++++++++++++--------------------
 1 files changed, 29 insertions(+), 20 deletions(-)

diffs (85 lines):

diff -r b1fbc3a22980 -r ebf4f0c26130 lib/libc/gmon/gmon.c
--- a/lib/libc/gmon/gmon.c      Thu May 05 22:02:17 2022 +0000
+++ b/lib/libc/gmon/gmon.c      Fri May 06 04:49:13 2022 +0000
@@ -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 @@
                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 @@
        } 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;



Home | Main Index | Thread Index | Old Index