148fb7bfaSmrg /* alloc.c -- Memory allocation without mmap.
2*b1e83836Smrg Copyright (C) 2012-2022 Free Software Foundation, Inc.
348fb7bfaSmrg Written by Ian Lance Taylor, Google.
448fb7bfaSmrg
548fb7bfaSmrg Redistribution and use in source and binary forms, with or without
648fb7bfaSmrg modification, are permitted provided that the following conditions are
748fb7bfaSmrg met:
848fb7bfaSmrg
948fb7bfaSmrg (1) Redistributions of source code must retain the above copyright
1048fb7bfaSmrg notice, this list of conditions and the following disclaimer.
1148fb7bfaSmrg
1248fb7bfaSmrg (2) Redistributions in binary form must reproduce the above copyright
1348fb7bfaSmrg notice, this list of conditions and the following disclaimer in
1448fb7bfaSmrg the documentation and/or other materials provided with the
1548fb7bfaSmrg distribution.
1648fb7bfaSmrg
1748fb7bfaSmrg (3) The name of the author may not be used to
1848fb7bfaSmrg endorse or promote products derived from this software without
1948fb7bfaSmrg specific prior written permission.
2048fb7bfaSmrg
2148fb7bfaSmrg THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2248fb7bfaSmrg IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2348fb7bfaSmrg WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2448fb7bfaSmrg DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
2548fb7bfaSmrg INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2648fb7bfaSmrg (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2748fb7bfaSmrg SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2848fb7bfaSmrg HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2948fb7bfaSmrg STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
3048fb7bfaSmrg IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3148fb7bfaSmrg POSSIBILITY OF SUCH DAMAGE. */
3248fb7bfaSmrg
3348fb7bfaSmrg #include "config.h"
3448fb7bfaSmrg
3548fb7bfaSmrg #include <errno.h>
3648fb7bfaSmrg #include <stdlib.h>
3748fb7bfaSmrg #include <sys/types.h>
3848fb7bfaSmrg
3948fb7bfaSmrg #include "backtrace.h"
4048fb7bfaSmrg #include "internal.h"
4148fb7bfaSmrg
4248fb7bfaSmrg /* Allocation routines to use on systems that do not support anonymous
4348fb7bfaSmrg mmap. This implementation just uses malloc, which means that the
4448fb7bfaSmrg backtrace functions may not be safely invoked from a signal
4548fb7bfaSmrg handler. */
4648fb7bfaSmrg
47f9a78e0eSmrg /* Allocate memory like malloc. If ERROR_CALLBACK is NULL, don't
48f9a78e0eSmrg report an error. */
4948fb7bfaSmrg
5048fb7bfaSmrg void *
backtrace_alloc(struct backtrace_state * state ATTRIBUTE_UNUSED,size_t size,backtrace_error_callback error_callback,void * data)5148fb7bfaSmrg backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED,
5248fb7bfaSmrg size_t size, backtrace_error_callback error_callback,
5348fb7bfaSmrg void *data)
5448fb7bfaSmrg {
5548fb7bfaSmrg void *ret;
5648fb7bfaSmrg
5748fb7bfaSmrg ret = malloc (size);
5848fb7bfaSmrg if (ret == NULL)
59f9a78e0eSmrg {
60f9a78e0eSmrg if (error_callback)
6148fb7bfaSmrg error_callback (data, "malloc", errno);
62f9a78e0eSmrg }
6348fb7bfaSmrg return ret;
6448fb7bfaSmrg }
6548fb7bfaSmrg
6648fb7bfaSmrg /* Free memory. */
6748fb7bfaSmrg
6848fb7bfaSmrg void
backtrace_free(struct backtrace_state * state ATTRIBUTE_UNUSED,void * p,size_t size ATTRIBUTE_UNUSED,backtrace_error_callback error_callback ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)6948fb7bfaSmrg backtrace_free (struct backtrace_state *state ATTRIBUTE_UNUSED,
7048fb7bfaSmrg void *p, size_t size ATTRIBUTE_UNUSED,
7148fb7bfaSmrg backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
7248fb7bfaSmrg void *data ATTRIBUTE_UNUSED)
7348fb7bfaSmrg {
7448fb7bfaSmrg free (p);
7548fb7bfaSmrg }
7648fb7bfaSmrg
7748fb7bfaSmrg /* Grow VEC by SIZE bytes. */
7848fb7bfaSmrg
7948fb7bfaSmrg void *
backtrace_vector_grow(struct backtrace_state * state ATTRIBUTE_UNUSED,size_t size,backtrace_error_callback error_callback,void * data,struct backtrace_vector * vec)8048fb7bfaSmrg backtrace_vector_grow (struct backtrace_state *state ATTRIBUTE_UNUSED,
8148fb7bfaSmrg size_t size, backtrace_error_callback error_callback,
8248fb7bfaSmrg void *data, struct backtrace_vector *vec)
8348fb7bfaSmrg {
8448fb7bfaSmrg void *ret;
8548fb7bfaSmrg
8648fb7bfaSmrg if (size > vec->alc)
8748fb7bfaSmrg {
8848fb7bfaSmrg size_t alc;
8948fb7bfaSmrg void *base;
9048fb7bfaSmrg
9148fb7bfaSmrg if (vec->size == 0)
9248fb7bfaSmrg alc = 32 * size;
9348fb7bfaSmrg else if (vec->size >= 4096)
9448fb7bfaSmrg alc = vec->size + 4096;
9548fb7bfaSmrg else
9648fb7bfaSmrg alc = 2 * vec->size;
9748fb7bfaSmrg
9848fb7bfaSmrg if (alc < vec->size + size)
9948fb7bfaSmrg alc = vec->size + size;
10048fb7bfaSmrg
10148fb7bfaSmrg base = realloc (vec->base, alc);
10248fb7bfaSmrg if (base == NULL)
10348fb7bfaSmrg {
10448fb7bfaSmrg error_callback (data, "realloc", errno);
10548fb7bfaSmrg return NULL;
10648fb7bfaSmrg }
10748fb7bfaSmrg
10848fb7bfaSmrg vec->base = base;
10948fb7bfaSmrg vec->alc = alc - vec->size;
11048fb7bfaSmrg }
11148fb7bfaSmrg
11248fb7bfaSmrg ret = (char *) vec->base + vec->size;
11348fb7bfaSmrg vec->size += size;
11448fb7bfaSmrg vec->alc -= size;
11548fb7bfaSmrg return ret;
11648fb7bfaSmrg }
11748fb7bfaSmrg
11848fb7bfaSmrg /* Finish the current allocation on VEC. */
11948fb7bfaSmrg
12048fb7bfaSmrg void *
backtrace_vector_finish(struct backtrace_state * state,struct backtrace_vector * vec,backtrace_error_callback error_callback,void * data)12148fb7bfaSmrg backtrace_vector_finish (struct backtrace_state *state,
12248fb7bfaSmrg struct backtrace_vector *vec,
12348fb7bfaSmrg backtrace_error_callback error_callback,
12448fb7bfaSmrg void *data)
12548fb7bfaSmrg {
12648fb7bfaSmrg void *ret;
12748fb7bfaSmrg
12848fb7bfaSmrg /* With this allocator we call realloc in backtrace_vector_grow,
12948fb7bfaSmrg which means we can't easily reuse the memory here. So just
13048fb7bfaSmrg release it. */
13148fb7bfaSmrg if (!backtrace_vector_release (state, vec, error_callback, data))
13248fb7bfaSmrg return NULL;
13348fb7bfaSmrg ret = vec->base;
13448fb7bfaSmrg vec->base = NULL;
13548fb7bfaSmrg vec->size = 0;
13648fb7bfaSmrg vec->alc = 0;
13748fb7bfaSmrg return ret;
13848fb7bfaSmrg }
13948fb7bfaSmrg
14048fb7bfaSmrg /* Release any extra space allocated for VEC. */
14148fb7bfaSmrg
14248fb7bfaSmrg int
backtrace_vector_release(struct backtrace_state * state ATTRIBUTE_UNUSED,struct backtrace_vector * vec,backtrace_error_callback error_callback,void * data)14348fb7bfaSmrg backtrace_vector_release (struct backtrace_state *state ATTRIBUTE_UNUSED,
14448fb7bfaSmrg struct backtrace_vector *vec,
14548fb7bfaSmrg backtrace_error_callback error_callback,
14648fb7bfaSmrg void *data)
14748fb7bfaSmrg {
148181254a7Smrg vec->alc = 0;
149181254a7Smrg
150181254a7Smrg if (vec->size == 0)
151181254a7Smrg {
152181254a7Smrg /* As of C17, realloc with size 0 is marked as an obsolescent feature, use
153181254a7Smrg free instead. */
154181254a7Smrg free (vec->base);
155181254a7Smrg vec->base = NULL;
156181254a7Smrg return 1;
157181254a7Smrg }
158181254a7Smrg
15948fb7bfaSmrg vec->base = realloc (vec->base, vec->size);
16048fb7bfaSmrg if (vec->base == NULL)
16148fb7bfaSmrg {
16248fb7bfaSmrg error_callback (data, "realloc", errno);
16348fb7bfaSmrg return 0;
16448fb7bfaSmrg }
165181254a7Smrg
16648fb7bfaSmrg return 1;
16748fb7bfaSmrg }
168