Home | History | Annotate | Line # | Download | only in libbacktrace
      1   1.1  mrg /* alloc.c -- Memory allocation without mmap.
      2  1.10  mrg    Copyright (C) 2012-2022 Free Software Foundation, Inc.
      3   1.1  mrg    Written by Ian Lance Taylor, Google.
      4   1.1  mrg 
      5   1.1  mrg Redistribution and use in source and binary forms, with or without
      6   1.1  mrg modification, are permitted provided that the following conditions are
      7   1.1  mrg met:
      8   1.1  mrg 
      9   1.1  mrg     (1) Redistributions of source code must retain the above copyright
     10   1.6  mrg     notice, this list of conditions and the following disclaimer.
     11   1.1  mrg 
     12   1.1  mrg     (2) Redistributions in binary form must reproduce the above copyright
     13   1.1  mrg     notice, this list of conditions and the following disclaimer in
     14   1.1  mrg     the documentation and/or other materials provided with the
     15   1.6  mrg     distribution.
     16   1.6  mrg 
     17   1.1  mrg     (3) The name of the author may not be used to
     18   1.1  mrg     endorse or promote products derived from this software without
     19   1.1  mrg     specific prior written permission.
     20   1.1  mrg 
     21   1.1  mrg THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22   1.1  mrg IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     23   1.1  mrg WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     24   1.1  mrg DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     25   1.1  mrg INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     26   1.1  mrg (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     27   1.1  mrg SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28   1.1  mrg HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     29   1.1  mrg STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     30   1.1  mrg IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31   1.1  mrg POSSIBILITY OF SUCH DAMAGE.  */
     32   1.1  mrg 
     33   1.1  mrg #include "config.h"
     34   1.1  mrg 
     35   1.1  mrg #include <errno.h>
     36   1.1  mrg #include <stdlib.h>
     37   1.1  mrg #include <sys/types.h>
     38   1.1  mrg 
     39   1.1  mrg #include "backtrace.h"
     40   1.1  mrg #include "internal.h"
     41   1.1  mrg 
     42   1.1  mrg /* Allocation routines to use on systems that do not support anonymous
     43   1.1  mrg    mmap.  This implementation just uses malloc, which means that the
     44   1.1  mrg    backtrace functions may not be safely invoked from a signal
     45   1.1  mrg    handler.  */
     46   1.1  mrg 
     47   1.4  mrg /* Allocate memory like malloc.  If ERROR_CALLBACK is NULL, don't
     48   1.4  mrg    report an error.  */
     49   1.1  mrg 
     50   1.1  mrg void *
     51   1.1  mrg backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED,
     52   1.1  mrg 		 size_t size, backtrace_error_callback error_callback,
     53   1.1  mrg 		 void *data)
     54   1.1  mrg {
     55   1.1  mrg   void *ret;
     56   1.1  mrg 
     57   1.1  mrg   ret = malloc (size);
     58   1.1  mrg   if (ret == NULL)
     59   1.4  mrg     {
     60   1.4  mrg       if (error_callback)
     61   1.4  mrg 	error_callback (data, "malloc", errno);
     62   1.4  mrg     }
     63   1.1  mrg   return ret;
     64   1.1  mrg }
     65   1.1  mrg 
     66   1.1  mrg /* Free memory.  */
     67   1.1  mrg 
     68   1.1  mrg void
     69   1.1  mrg backtrace_free (struct backtrace_state *state ATTRIBUTE_UNUSED,
     70   1.1  mrg 		void *p, size_t size ATTRIBUTE_UNUSED,
     71   1.1  mrg 		backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
     72   1.1  mrg 		void *data ATTRIBUTE_UNUSED)
     73   1.1  mrg {
     74   1.1  mrg   free (p);
     75   1.1  mrg }
     76   1.1  mrg 
     77   1.1  mrg /* Grow VEC by SIZE bytes.  */
     78   1.1  mrg 
     79   1.1  mrg void *
     80   1.1  mrg backtrace_vector_grow (struct backtrace_state *state ATTRIBUTE_UNUSED,
     81   1.1  mrg 		       size_t size, backtrace_error_callback error_callback,
     82   1.1  mrg 		       void *data, struct backtrace_vector *vec)
     83   1.1  mrg {
     84   1.1  mrg   void *ret;
     85   1.1  mrg 
     86   1.1  mrg   if (size > vec->alc)
     87   1.1  mrg     {
     88   1.1  mrg       size_t alc;
     89   1.1  mrg       void *base;
     90   1.1  mrg 
     91   1.1  mrg       if (vec->size == 0)
     92   1.1  mrg 	alc = 32 * size;
     93   1.1  mrg       else if (vec->size >= 4096)
     94   1.1  mrg 	alc = vec->size + 4096;
     95   1.1  mrg       else
     96   1.1  mrg 	alc = 2 * vec->size;
     97   1.1  mrg 
     98   1.1  mrg       if (alc < vec->size + size)
     99   1.1  mrg 	alc = vec->size + size;
    100   1.1  mrg 
    101   1.1  mrg       base = realloc (vec->base, alc);
    102   1.1  mrg       if (base == NULL)
    103   1.1  mrg 	{
    104   1.1  mrg 	  error_callback (data, "realloc", errno);
    105   1.1  mrg 	  return NULL;
    106   1.1  mrg 	}
    107   1.1  mrg 
    108   1.1  mrg       vec->base = base;
    109   1.1  mrg       vec->alc = alc - vec->size;
    110   1.1  mrg     }
    111   1.1  mrg 
    112   1.1  mrg   ret = (char *) vec->base + vec->size;
    113   1.1  mrg   vec->size += size;
    114   1.1  mrg   vec->alc -= size;
    115   1.1  mrg   return ret;
    116   1.1  mrg }
    117   1.1  mrg 
    118   1.1  mrg /* Finish the current allocation on VEC.  */
    119   1.1  mrg 
    120   1.1  mrg void *
    121   1.1  mrg backtrace_vector_finish (struct backtrace_state *state,
    122   1.1  mrg 			 struct backtrace_vector *vec,
    123   1.1  mrg 			 backtrace_error_callback error_callback,
    124   1.1  mrg 			 void *data)
    125   1.1  mrg {
    126   1.1  mrg   void *ret;
    127   1.1  mrg 
    128   1.1  mrg   /* With this allocator we call realloc in backtrace_vector_grow,
    129   1.1  mrg      which means we can't easily reuse the memory here.  So just
    130   1.1  mrg      release it.  */
    131   1.1  mrg   if (!backtrace_vector_release (state, vec, error_callback, data))
    132   1.1  mrg     return NULL;
    133   1.1  mrg   ret = vec->base;
    134   1.1  mrg   vec->base = NULL;
    135   1.1  mrg   vec->size = 0;
    136   1.1  mrg   vec->alc = 0;
    137   1.1  mrg   return ret;
    138   1.1  mrg }
    139   1.1  mrg 
    140   1.1  mrg /* Release any extra space allocated for VEC.  */
    141   1.1  mrg 
    142   1.1  mrg int
    143   1.1  mrg backtrace_vector_release (struct backtrace_state *state ATTRIBUTE_UNUSED,
    144   1.1  mrg 			  struct backtrace_vector *vec,
    145   1.1  mrg 			  backtrace_error_callback error_callback,
    146   1.1  mrg 			  void *data)
    147   1.1  mrg {
    148   1.8  mrg   vec->alc = 0;
    149   1.8  mrg 
    150   1.8  mrg   if (vec->size == 0)
    151   1.8  mrg     {
    152   1.8  mrg       /* As of C17, realloc with size 0 is marked as an obsolescent feature, use
    153   1.8  mrg 	 free instead.  */
    154   1.8  mrg       free (vec->base);
    155   1.8  mrg       vec->base = NULL;
    156   1.8  mrg       return 1;
    157   1.8  mrg     }
    158   1.8  mrg 
    159   1.1  mrg   vec->base = realloc (vec->base, vec->size);
    160   1.1  mrg   if (vec->base == NULL)
    161   1.1  mrg     {
    162   1.1  mrg       error_callback (data, "realloc", errno);
    163   1.1  mrg       return 0;
    164   1.1  mrg     }
    165   1.8  mrg 
    166   1.1  mrg   return 1;
    167   1.1  mrg }
    168