|
1 /* |
|
2 |
|
3 Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. |
|
4 Portions Copyright 2002,2007 Sun Microsystems, Inc. All rights reserved. |
|
5 |
|
6 This program is free software; you can redistribute it and/or modify it |
|
7 under the terms of version 2.1 of the GNU Lesser General Public License |
|
8 as published by the Free Software Foundation. |
|
9 |
|
10 This program is distributed in the hope that it would be useful, but |
|
11 WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
13 |
|
14 Further, this software is distributed without any warranty that it is |
|
15 free of the rightful claim of any third person regarding infringement |
|
16 or the like. Any license provided herein, whether implied or |
|
17 otherwise, applies only to this software file. Patent licenses, if |
|
18 any, provided herein do not apply to combinations of this program with |
|
19 other software, or any other product whatsoever. |
|
20 |
|
21 You should have received a copy of the GNU Lesser General Public |
|
22 License along with this program; if not, write the Free Software |
|
23 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, |
|
24 USA. |
|
25 |
|
26 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, |
|
27 Mountain View, CA 94043, or: |
|
28 |
|
29 http://www.sgi.com |
|
30 |
|
31 For further information regarding this notice, see: |
|
32 |
|
33 http://oss.sgi.com/projects/GenInfo/NoticeExplan |
|
34 |
|
35 */ |
|
36 |
|
37 |
|
38 |
|
39 #include "config.h" |
|
40 #include "pro_incl.h" |
|
41 #ifdef HAVE_STDLIB_H |
|
42 #include <stdlib.h> |
|
43 #endif /* HAVE_STDLIB_H */ |
|
44 #ifdef HAVE_STRING_H |
|
45 #include <string.h> |
|
46 #endif /* HAVE_STRING_H */ |
|
47 #include <malloc.h> |
|
48 |
|
49 /* |
|
50 When each block is allocated, there is a two-word structure |
|
51 allocated at the beginning so the block can go on a list. |
|
52 The address returned is the address *after* the two pointers |
|
53 at the start. But this allows us to be given a pointer to |
|
54 a generic block, and go backwards to find the list-node. Then |
|
55 we can remove this block from it's list without the need to search |
|
56 through a linked list in order to remove the node. It also allows |
|
57 us to 'delete' a memory block without needing the dbg structure. |
|
58 We still need the dbg structure on allocation so that we know which |
|
59 linked list to add the block to. |
|
60 |
|
61 Only the allocation of the dbg structure itself cannot use _dwarf_p_get_alloc. |
|
62 That structure should be set up by hand, and the two list pointers |
|
63 should be initialized to point at the node itself. That initializes |
|
64 the doubly linked list. |
|
65 */ |
|
66 |
|
67 #define LIST_TO_BLOCK(lst) ((void*) (((char *)lst) + sizeof(memory_list_t))) |
|
68 #define BLOCK_TO_LIST(blk) ((memory_list_t*) (((char*)blk) - sizeof(memory_list_t))) |
|
69 |
|
70 |
|
71 /* |
|
72 dbg should be NULL only when allocating dbg itself. In that |
|
73 case we initialize it to an empty circular doubly-linked list. |
|
74 */ |
|
75 |
|
76 Dwarf_Ptr |
|
77 _dwarf_p_get_alloc(Dwarf_P_Debug dbg, Dwarf_Unsigned size) |
|
78 { |
|
79 void *sp; |
|
80 memory_list_t *lp = NULL; |
|
81 memory_list_t *dbglp = NULL; |
|
82 memory_list_t *nextblock = NULL; |
|
83 |
|
84 /* alloc control struct and data block together for performance reasons */ |
|
85 lp = (memory_list_t *) malloc(size + sizeof(memory_list_t)); |
|
86 if (lp == NULL) { |
|
87 /* should throw an error */ |
|
88 return NULL; |
|
89 } |
|
90 |
|
91 /* point to 'size' bytes just beyond lp struct */ |
|
92 sp = LIST_TO_BLOCK(lp); |
|
93 memset(sp, 0, size); |
|
94 |
|
95 if (dbg == NULL) { |
|
96 lp->next = lp->prev = lp; |
|
97 } else { |
|
98 /* I always have to draw a picture to understand this part. */ |
|
99 |
|
100 dbglp = BLOCK_TO_LIST(dbg); |
|
101 nextblock = dbglp->next; |
|
102 |
|
103 /* Insert between dbglp and nextblock */ |
|
104 dbglp->next = lp; |
|
105 lp->prev = dbglp; |
|
106 lp->next = nextblock; |
|
107 nextblock->prev = lp; |
|
108 } |
|
109 |
|
110 return sp; |
|
111 } |
|
112 |
|
113 /* |
|
114 This routine is only here in case a caller of an older version of the |
|
115 library is calling this for some reason. |
|
116 We will clean up any stray blocks when the session is closed. |
|
117 No need to remove this block. In theory the user might be depending on the fact |
|
118 that we used to just 'free' this. In theory they might also be |
|
119 passing a block that they got from libdwarf. So we don't know if we |
|
120 should try to remove this block from our global list. Safest just to |
|
121 do nothing at this point. |
|
122 |
|
123 !!! |
|
124 This function is deprecated! Don't call it inside libdwarf or outside of it. |
|
125 !!! |
|
126 */ |
|
127 |
|
128 void |
|
129 dwarf_p_dealloc(Dwarf_Small * ptr) |
|
130 { |
|
131 return; |
|
132 } |
|
133 |
|
134 /* |
|
135 The dbg structure is not needed here anymore. |
|
136 */ |
|
137 |
|
138 void |
|
139 _dwarf_p_dealloc(Dwarf_P_Debug dbg, Dwarf_Small * ptr) /* ARGSUSED */ |
|
140 { |
|
141 memory_list_t *lp; |
|
142 lp = BLOCK_TO_LIST(ptr); |
|
143 |
|
144 /* |
|
145 Remove from a doubly linked, circular list. |
|
146 Read carefully, use a white board if necessary. |
|
147 If this is an empty list, the following statements are no-ops, and |
|
148 will write to the same memory location they read from. |
|
149 This should only happen when we deallocate the dbg structure itself. |
|
150 */ |
|
151 |
|
152 lp->prev->next = lp->next; |
|
153 lp->next->prev = lp->prev; |
|
154 |
|
155 free((void*)lp); |
|
156 } |
|
157 |
|
158 |
|
159 /* |
|
160 This routine deallocates all the nodes on the dbg list, |
|
161 and then deallocates the dbg structure itself. |
|
162 */ |
|
163 |
|
164 void |
|
165 _dwarf_p_dealloc_all(Dwarf_P_Debug dbg) |
|
166 { |
|
167 memory_list_t *dbglp; |
|
168 |
|
169 if (dbg == NULL) { |
|
170 /* should throw an error */ |
|
171 return; |
|
172 } |
|
173 |
|
174 dbglp = BLOCK_TO_LIST(dbg); |
|
175 while (dbglp->next != dbglp) { |
|
176 _dwarf_p_dealloc(dbg, LIST_TO_BLOCK(dbglp->next)); |
|
177 } |
|
178 if (dbglp->next != dbglp || |
|
179 dbglp->prev != dbglp) { |
|
180 |
|
181 /* should throw error */ |
|
182 /* For some reason we couldn't free all the blocks? */ |
|
183 return; |
|
184 } |
|
185 _dwarf_p_dealloc(NULL, (void*)dbg); |
|
186 } |
|
187 |