alloc.c revision 1.1.1.1 1 1.1 mrg /* alloc.c -- Memory allocation without mmap.
2 1.1 mrg Copyright (C) 2012-2013 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 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 mrg distribution.
16 1.1 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 mrg /* Allocate memory like malloc. */
48 1.1 mrg
49 1.1 mrg void *
50 1.1 mrg backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED,
51 1.1 mrg size_t size, backtrace_error_callback error_callback,
52 1.1 mrg void *data)
53 1.1 mrg {
54 1.1 mrg void *ret;
55 1.1 mrg
56 1.1 mrg ret = malloc (size);
57 1.1 mrg if (ret == NULL)
58 1.1 mrg error_callback (data, "malloc", errno);
59 1.1 mrg return ret;
60 1.1 mrg }
61 1.1 mrg
62 1.1 mrg /* Free memory. */
63 1.1 mrg
64 1.1 mrg void
65 1.1 mrg backtrace_free (struct backtrace_state *state ATTRIBUTE_UNUSED,
66 1.1 mrg void *p, size_t size ATTRIBUTE_UNUSED,
67 1.1 mrg backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
68 1.1 mrg void *data ATTRIBUTE_UNUSED)
69 1.1 mrg {
70 1.1 mrg free (p);
71 1.1 mrg }
72 1.1 mrg
73 1.1 mrg /* Grow VEC by SIZE bytes. */
74 1.1 mrg
75 1.1 mrg void *
76 1.1 mrg backtrace_vector_grow (struct backtrace_state *state ATTRIBUTE_UNUSED,
77 1.1 mrg size_t size, backtrace_error_callback error_callback,
78 1.1 mrg void *data, struct backtrace_vector *vec)
79 1.1 mrg {
80 1.1 mrg void *ret;
81 1.1 mrg
82 1.1 mrg if (size > vec->alc)
83 1.1 mrg {
84 1.1 mrg size_t alc;
85 1.1 mrg void *base;
86 1.1 mrg
87 1.1 mrg if (vec->size == 0)
88 1.1 mrg alc = 32 * size;
89 1.1 mrg else if (vec->size >= 4096)
90 1.1 mrg alc = vec->size + 4096;
91 1.1 mrg else
92 1.1 mrg alc = 2 * vec->size;
93 1.1 mrg
94 1.1 mrg if (alc < vec->size + size)
95 1.1 mrg alc = vec->size + size;
96 1.1 mrg
97 1.1 mrg base = realloc (vec->base, alc);
98 1.1 mrg if (base == NULL)
99 1.1 mrg {
100 1.1 mrg error_callback (data, "realloc", errno);
101 1.1 mrg return NULL;
102 1.1 mrg }
103 1.1 mrg
104 1.1 mrg vec->base = base;
105 1.1 mrg vec->alc = alc - vec->size;
106 1.1 mrg }
107 1.1 mrg
108 1.1 mrg ret = (char *) vec->base + vec->size;
109 1.1 mrg vec->size += size;
110 1.1 mrg vec->alc -= size;
111 1.1 mrg return ret;
112 1.1 mrg }
113 1.1 mrg
114 1.1 mrg /* Finish the current allocation on VEC. */
115 1.1 mrg
116 1.1 mrg void *
117 1.1 mrg backtrace_vector_finish (struct backtrace_state *state,
118 1.1 mrg struct backtrace_vector *vec,
119 1.1 mrg backtrace_error_callback error_callback,
120 1.1 mrg void *data)
121 1.1 mrg {
122 1.1 mrg void *ret;
123 1.1 mrg
124 1.1 mrg /* With this allocator we call realloc in backtrace_vector_grow,
125 1.1 mrg which means we can't easily reuse the memory here. So just
126 1.1 mrg release it. */
127 1.1 mrg if (!backtrace_vector_release (state, vec, error_callback, data))
128 1.1 mrg return NULL;
129 1.1 mrg ret = vec->base;
130 1.1 mrg vec->base = NULL;
131 1.1 mrg vec->size = 0;
132 1.1 mrg vec->alc = 0;
133 1.1 mrg return ret;
134 1.1 mrg }
135 1.1 mrg
136 1.1 mrg /* Release any extra space allocated for VEC. */
137 1.1 mrg
138 1.1 mrg int
139 1.1 mrg backtrace_vector_release (struct backtrace_state *state ATTRIBUTE_UNUSED,
140 1.1 mrg struct backtrace_vector *vec,
141 1.1 mrg backtrace_error_callback error_callback,
142 1.1 mrg void *data)
143 1.1 mrg {
144 1.1 mrg vec->base = realloc (vec->base, vec->size);
145 1.1 mrg if (vec->base == NULL)
146 1.1 mrg {
147 1.1 mrg error_callback (data, "realloc", errno);
148 1.1 mrg return 0;
149 1.1 mrg }
150 1.1 mrg vec->alc = 0;
151 1.1 mrg return 1;
152 1.1 mrg }
153