xref: /netbsd-src/external/gpl3/gcc.old/dist/libbacktrace/alloc.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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