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