14226f635SJason King /*
24226f635SJason King  * This file and its contents are supplied under the terms of the
34226f635SJason King  * Common Development and Distribution License ("CDDL"), version 1.0.
44226f635SJason King  * You may only use this file in accordance with the terms of version
54226f635SJason King  * 1.0 of the CDDL.
64226f635SJason King  *
74226f635SJason King  * A full copy of the text of the CDDL should have accompanied this
84226f635SJason King  * source.  A copy of the CDDL is also available via the Internet at
94226f635SJason King  * http://www.illumos.org/license/CDDL.
104226f635SJason King  */
114226f635SJason King 
124226f635SJason King /*
134226f635SJason King  * Copyright 2017 Jason King
146a6cfa5dSJason King  * Copyright 2019, Joyent, Inc.
154226f635SJason King  */
164226f635SJason King 
17*1cd08393SJason King #include <errno.h>
18*1cd08393SJason King #include <limits.h>
194226f635SJason King #include <stdlib.h>
204226f635SJason King #include <string.h>
214226f635SJason King #include "demangle-sys.h"
224226f635SJason King #include "demangle_int.h"
234226f635SJason King 
244226f635SJason King void *
zalloc(sysdem_ops_t * ops,size_t len)254226f635SJason King zalloc(sysdem_ops_t *ops, size_t len)
264226f635SJason King {
274226f635SJason King 	void *p = ops->alloc(len);
284226f635SJason King 
294226f635SJason King 	if (p != NULL)
304226f635SJason King 		(void) memset(p, 0, len);
314226f635SJason King 
324226f635SJason King #ifdef DEBUG
334226f635SJason King 	/*
344226f635SJason King 	 * In normal operation, we should never exhaust memory.  Either
354226f635SJason King 	 * something's wrong, or the system is so hosed that aborting
364226f635SJason King 	 * shouldn't hurt anything, and it gives us a more useful stack
374226f635SJason King 	 * trace.
384226f635SJason King 	 */
394226f635SJason King 	if (p == NULL)
404226f635SJason King 		abort();
414226f635SJason King #endif
424226f635SJason King 
434226f635SJason King 	return (p);
444226f635SJason King }
454226f635SJason King 
46*1cd08393SJason King void *
xcalloc(sysdem_ops_t * ops,size_t n,size_t elsize)47*1cd08393SJason King xcalloc(sysdem_ops_t *ops, size_t n, size_t elsize)
48*1cd08393SJason King {
49*1cd08393SJason King 	uint64_t sz;
50*1cd08393SJason King 
51*1cd08393SJason King 	if (mul_overflow(n, elsize, &sz)) {
52*1cd08393SJason King 		errno = ENOMEM;
53*1cd08393SJason King 		return (NULL);
54*1cd08393SJason King 	}
55*1cd08393SJason King 
56*1cd08393SJason King #ifndef _LP64
57*1cd08393SJason King 	if (sz > SIZE_MAX) {
58*1cd08393SJason King 		errno = ENOMEM;
59*1cd08393SJason King 		return (NULL);
60*1cd08393SJason King 	}
61*1cd08393SJason King #endif
62*1cd08393SJason King 
63*1cd08393SJason King 	return (zalloc(ops, sz));
64*1cd08393SJason King }
654226f635SJason King void
xfree(sysdem_ops_t * ops,void * p,size_t len)664226f635SJason King xfree(sysdem_ops_t *ops, void *p, size_t len)
674226f635SJason King {
684226f635SJason King 	if (p == NULL || len == 0)
694226f635SJason King 		return;
704226f635SJason King 
714226f635SJason King 	ops->free(p, len);
724226f635SJason King }
734226f635SJason King 
744226f635SJason King void *
xrealloc(sysdem_ops_t * ops,void * p,size_t oldsz,size_t newsz)754226f635SJason King xrealloc(sysdem_ops_t *ops, void *p, size_t oldsz, size_t newsz)
764226f635SJason King {
774226f635SJason King 	if (newsz == oldsz)
784226f635SJason King 		return (p);
794226f635SJason King 
804226f635SJason King 	VERIFY3U(newsz, >, oldsz);
814226f635SJason King 
824226f635SJason King 	void *temp = zalloc(ops, newsz);
834226f635SJason King 
844226f635SJason King 	if (temp == NULL)
854226f635SJason King 		return (NULL);
864226f635SJason King 
874226f635SJason King 	if (oldsz > 0) {
884226f635SJason King 		(void) memcpy(temp, p, oldsz);
894226f635SJason King 		xfree(ops, p, oldsz);
904226f635SJason King 	}
914226f635SJason King 
924226f635SJason King 	return (temp);
934226f635SJason King }
944226f635SJason King 
956a6cfa5dSJason King char *
xstrdup(sysdem_ops_t * ops,const char * src)966a6cfa5dSJason King xstrdup(sysdem_ops_t *ops, const char *src)
976a6cfa5dSJason King {
986a6cfa5dSJason King 	size_t len = strlen(src);
996a6cfa5dSJason King 	char *str = zalloc(ops, len + 1);
1006a6cfa5dSJason King 
1016a6cfa5dSJason King 	if (str == NULL)
1026a6cfa5dSJason King 		return (NULL);
1036a6cfa5dSJason King 
1046a6cfa5dSJason King 	/* zalloc(len+1) guarantees this will be NUL-terminated */
1056a6cfa5dSJason King 	(void) memcpy(str, src, len);
1066a6cfa5dSJason King 	return (str);
1076a6cfa5dSJason King }
1086a6cfa5dSJason King 
1094226f635SJason King /*ARGSUSED*/
1104226f635SJason King static void
def_free(void * p,size_t len)1114226f635SJason King def_free(void *p, size_t len)
1124226f635SJason King {
1134226f635SJason King 	free(p);
1144226f635SJason King }
1154226f635SJason King 
1164226f635SJason King static sysdem_ops_t i_sysdem_ops_default = {
1174226f635SJason King 	.alloc = malloc,
1184226f635SJason King 	.free = def_free
1194226f635SJason King };
1204226f635SJason King sysdem_ops_t *sysdem_ops_default = &i_sysdem_ops_default;
121