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