alloc.c revision 1.1.1.8 1 1.1 mrg /* alloc.c -- Memory allocation without mmap.
2 1.1.1.8 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.1.1.4 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.1.1.4 mrg distribution.
16 1.1.1.4 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.1.1.3 mrg /* Allocate memory like malloc. If ERROR_CALLBACK is NULL, don't
48 1.1.1.3 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.1.1.3 mrg {
60 1.1.1.3 mrg if (error_callback)
61 1.1.1.3 mrg error_callback (data, "malloc", errno);
62 1.1.1.3 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.1.1.6 mrg vec->alc = 0;
149 1.1.1.6 mrg
150 1.1.1.6 mrg if (vec->size == 0)
151 1.1.1.6 mrg {
152 1.1.1.6 mrg /* As of C17, realloc with size 0 is marked as an obsolescent feature, use
153 1.1.1.6 mrg free instead. */
154 1.1.1.6 mrg free (vec->base);
155 1.1.1.6 mrg vec->base = NULL;
156 1.1.1.6 mrg return 1;
157 1.1.1.6 mrg }
158 1.1.1.6 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.1.1.6 mrg
166 1.1 mrg return 1;
167 1.1 mrg }
168