git: c29ee08204ce - main - rtld_malloc: add __crt_aligned_alloc_offset()

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Mon, 21 Aug 2023 14:17:17 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=c29ee08204ce4106d4992474005c5f2fb7d5fbf1

commit c29ee08204ce4106d4992474005c5f2fb7d5fbf1
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2023-07-22 04:21:45 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2023-08-21 14:16:42 +0000

    rtld_malloc: add __crt_aligned_alloc_offset()
    
    It is modelled after aligned_alloc(3).  Most importantly, to free the
    allocation, __crt_free() can be used.  Additionally, caller may specify
    offset into the aligned allocation, so that we return offset-ed from
    alignment pointer.
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D41150
---
 libexec/rtld-elf/rtld_malloc.c | 34 +++++++++++++++++++++++++++++++---
 libexec/rtld-elf/rtld_malloc.h |  1 +
 2 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/libexec/rtld-elf/rtld_malloc.c b/libexec/rtld-elf/rtld_malloc.c
index ac8af4d6b6e1..6e011e88ba5a 100644
--- a/libexec/rtld-elf/rtld_malloc.c
+++ b/libexec/rtld-elf/rtld_malloc.c
@@ -86,13 +86,15 @@ static void morecore(int bucket);
 static int morepages(int n);
 
 #define	MAGIC		0xef		/* magic # on accounting info */
+#define	AMAGIC		0xdf		/* magic # for aligned alloc */
 
 /*
  * nextf[i] is the pointer to the next free block of size
  * (FIRST_BUCKET_SIZE << i).  The overhead information precedes the data
  * area returned to the user.
  */
-#define	FIRST_BUCKET_SIZE	8
+#define	LOW_BITS		3
+#define	FIRST_BUCKET_SIZE	(1U << LOW_BITS)
 #define	NBUCKETS 30
 static	union overhead *nextf[NBUCKETS];
 
@@ -169,6 +171,28 @@ __crt_calloc(size_t num, size_t size)
 	return (ret);
 }
 
+void *
+__crt_aligned_alloc_offset(size_t align, size_t size, size_t offset)
+{
+	void *mem, *ov;
+	union overhead ov1;
+	uintptr_t x;
+
+	if (align < FIRST_BUCKET_SIZE)
+		align = FIRST_BUCKET_SIZE;
+	offset &= align - 1;
+	mem = __crt_malloc(size + align + offset + sizeof(union overhead));
+	if (mem == NULL)
+		return (NULL);
+	x = roundup2((uintptr_t)mem + sizeof(union overhead), align);
+	x += offset;
+	ov = cp2op((void *)x);
+	ov1.ov_magic = AMAGIC;
+	ov1.ov_index = x - (uintptr_t)mem - sizeof(union overhead);
+	memcpy(ov, &ov1, sizeof(ov1));
+	return ((void *)x);
+}
+
 /*
  * Allocate more memory to the indicated bucket.
  */
@@ -210,12 +234,16 @@ morecore(int bucket)
 void
 __crt_free(void *cp)
 {
+	union overhead *op, op1;
+	void *opx;
 	int size;
-	union overhead *op;
 
   	if (cp == NULL)
   		return;
-	op = cp2op(cp);
+	opx = cp2op(cp);
+	memcpy(&op1, opx, sizeof(op1));
+	op = op1.ov_magic == AMAGIC ? (void *)((caddr_t)cp - op1.ov_index) :
+	    opx;
 	if (op->ov_magic != MAGIC)
 		return;				/* sanity */
   	size = op->ov_index;
diff --git a/libexec/rtld-elf/rtld_malloc.h b/libexec/rtld-elf/rtld_malloc.h
index f9780c552821..247726b9f470 100644
--- a/libexec/rtld-elf/rtld_malloc.h
+++ b/libexec/rtld-elf/rtld_malloc.h
@@ -32,6 +32,7 @@
 #ifndef RTLD_MALLOC_H
 #define	RTLD_MALLOC_H
 
+void *__crt_aligned_alloc_offset(size_t align, size_t size, size_t offset);
 void *__crt_calloc(size_t num, size_t size);
 void __crt_free(void *cp);
 void *__crt_malloc(size_t nbytes);