136ac495dSmrg /* alloc.c -- Memory allocation without mmap.
2*8feb0f0bSmrg Copyright (C) 2012-2020 Free Software Foundation, Inc.
336ac495dSmrg Written by Ian Lance Taylor, Google.
436ac495dSmrg
536ac495dSmrg Redistribution and use in source and binary forms, with or without
636ac495dSmrg modification, are permitted provided that the following conditions are
736ac495dSmrg met:
836ac495dSmrg
936ac495dSmrg (1) Redistributions of source code must retain the above copyright
1036ac495dSmrg notice, this list of conditions and the following disclaimer.
1136ac495dSmrg
1236ac495dSmrg (2) Redistributions in binary form must reproduce the above copyright
1336ac495dSmrg notice, this list of conditions and the following disclaimer in
1436ac495dSmrg the documentation and/or other materials provided with the
1536ac495dSmrg distribution.
1636ac495dSmrg
1736ac495dSmrg (3) The name of the author may not be used to
1836ac495dSmrg endorse or promote products derived from this software without
1936ac495dSmrg specific prior written permission.
2036ac495dSmrg
2136ac495dSmrg THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2236ac495dSmrg IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2336ac495dSmrg WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2436ac495dSmrg DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
2536ac495dSmrg INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2636ac495dSmrg (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2736ac495dSmrg SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2836ac495dSmrg HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2936ac495dSmrg STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
3036ac495dSmrg IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3136ac495dSmrg POSSIBILITY OF SUCH DAMAGE. */
3236ac495dSmrg
3336ac495dSmrg #include "config.h"
3436ac495dSmrg
3536ac495dSmrg #include <errno.h>
3636ac495dSmrg #include <stdlib.h>
3736ac495dSmrg #include <sys/types.h>
3836ac495dSmrg
3936ac495dSmrg #include "backtrace.h"
4036ac495dSmrg #include "internal.h"
4136ac495dSmrg
4236ac495dSmrg /* Allocation routines to use on systems that do not support anonymous
4336ac495dSmrg mmap. This implementation just uses malloc, which means that the
4436ac495dSmrg backtrace functions may not be safely invoked from a signal
4536ac495dSmrg handler. */
4636ac495dSmrg
4736ac495dSmrg /* Allocate memory like malloc. If ERROR_CALLBACK is NULL, don't
4836ac495dSmrg report an error. */
4936ac495dSmrg
5036ac495dSmrg void *
backtrace_alloc(struct backtrace_state * state ATTRIBUTE_UNUSED,size_t size,backtrace_error_callback error_callback,void * data)5136ac495dSmrg backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED,
5236ac495dSmrg size_t size, backtrace_error_callback error_callback,
5336ac495dSmrg void *data)
5436ac495dSmrg {
5536ac495dSmrg void *ret;
5636ac495dSmrg
5736ac495dSmrg ret = malloc (size);
5836ac495dSmrg if (ret == NULL)
5936ac495dSmrg {
6036ac495dSmrg if (error_callback)
6136ac495dSmrg error_callback (data, "malloc", errno);
6236ac495dSmrg }
6336ac495dSmrg return ret;
6436ac495dSmrg }
6536ac495dSmrg
6636ac495dSmrg /* Free memory. */
6736ac495dSmrg
6836ac495dSmrg 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)6936ac495dSmrg backtrace_free (struct backtrace_state *state ATTRIBUTE_UNUSED,
7036ac495dSmrg void *p, size_t size ATTRIBUTE_UNUSED,
7136ac495dSmrg backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
7236ac495dSmrg void *data ATTRIBUTE_UNUSED)
7336ac495dSmrg {
7436ac495dSmrg free (p);
7536ac495dSmrg }
7636ac495dSmrg
7736ac495dSmrg /* Grow VEC by SIZE bytes. */
7836ac495dSmrg
7936ac495dSmrg void *
backtrace_vector_grow(struct backtrace_state * state ATTRIBUTE_UNUSED,size_t size,backtrace_error_callback error_callback,void * data,struct backtrace_vector * vec)8036ac495dSmrg backtrace_vector_grow (struct backtrace_state *state ATTRIBUTE_UNUSED,
8136ac495dSmrg size_t size, backtrace_error_callback error_callback,
8236ac495dSmrg void *data, struct backtrace_vector *vec)
8336ac495dSmrg {
8436ac495dSmrg void *ret;
8536ac495dSmrg
8636ac495dSmrg if (size > vec->alc)
8736ac495dSmrg {
8836ac495dSmrg size_t alc;
8936ac495dSmrg void *base;
9036ac495dSmrg
9136ac495dSmrg if (vec->size == 0)
9236ac495dSmrg alc = 32 * size;
9336ac495dSmrg else if (vec->size >= 4096)
9436ac495dSmrg alc = vec->size + 4096;
9536ac495dSmrg else
9636ac495dSmrg alc = 2 * vec->size;
9736ac495dSmrg
9836ac495dSmrg if (alc < vec->size + size)
9936ac495dSmrg alc = vec->size + size;
10036ac495dSmrg
10136ac495dSmrg base = realloc (vec->base, alc);
10236ac495dSmrg if (base == NULL)
10336ac495dSmrg {
10436ac495dSmrg error_callback (data, "realloc", errno);
10536ac495dSmrg return NULL;
10636ac495dSmrg }
10736ac495dSmrg
10836ac495dSmrg vec->base = base;
10936ac495dSmrg vec->alc = alc - vec->size;
11036ac495dSmrg }
11136ac495dSmrg
11236ac495dSmrg ret = (char *) vec->base + vec->size;
11336ac495dSmrg vec->size += size;
11436ac495dSmrg vec->alc -= size;
11536ac495dSmrg return ret;
11636ac495dSmrg }
11736ac495dSmrg
11836ac495dSmrg /* Finish the current allocation on VEC. */
11936ac495dSmrg
12036ac495dSmrg void *
backtrace_vector_finish(struct backtrace_state * state,struct backtrace_vector * vec,backtrace_error_callback error_callback,void * data)12136ac495dSmrg backtrace_vector_finish (struct backtrace_state *state,
12236ac495dSmrg struct backtrace_vector *vec,
12336ac495dSmrg backtrace_error_callback error_callback,
12436ac495dSmrg void *data)
12536ac495dSmrg {
12636ac495dSmrg void *ret;
12736ac495dSmrg
12836ac495dSmrg /* With this allocator we call realloc in backtrace_vector_grow,
12936ac495dSmrg which means we can't easily reuse the memory here. So just
13036ac495dSmrg release it. */
13136ac495dSmrg if (!backtrace_vector_release (state, vec, error_callback, data))
13236ac495dSmrg return NULL;
13336ac495dSmrg ret = vec->base;
13436ac495dSmrg vec->base = NULL;
13536ac495dSmrg vec->size = 0;
13636ac495dSmrg vec->alc = 0;
13736ac495dSmrg return ret;
13836ac495dSmrg }
13936ac495dSmrg
14036ac495dSmrg /* Release any extra space allocated for VEC. */
14136ac495dSmrg
14236ac495dSmrg int
backtrace_vector_release(struct backtrace_state * state ATTRIBUTE_UNUSED,struct backtrace_vector * vec,backtrace_error_callback error_callback,void * data)14336ac495dSmrg backtrace_vector_release (struct backtrace_state *state ATTRIBUTE_UNUSED,
14436ac495dSmrg struct backtrace_vector *vec,
14536ac495dSmrg backtrace_error_callback error_callback,
14636ac495dSmrg void *data)
14736ac495dSmrg {
148c0a68be4Smrg vec->alc = 0;
149c0a68be4Smrg
150c0a68be4Smrg if (vec->size == 0)
151c0a68be4Smrg {
152c0a68be4Smrg /* As of C17, realloc with size 0 is marked as an obsolescent feature, use
153c0a68be4Smrg free instead. */
154c0a68be4Smrg free (vec->base);
155c0a68be4Smrg vec->base = NULL;
156c0a68be4Smrg return 1;
157c0a68be4Smrg }
158c0a68be4Smrg
15936ac495dSmrg vec->base = realloc (vec->base, vec->size);
16036ac495dSmrg if (vec->base == NULL)
16136ac495dSmrg {
16236ac495dSmrg error_callback (data, "realloc", errno);
16336ac495dSmrg return 0;
16436ac495dSmrg }
165c0a68be4Smrg
16636ac495dSmrg return 1;
16736ac495dSmrg }
168