new gas main line
[deliverable/binutils-gdb.git] / gas / obsolete / gdb-blocks.c
1 /* gdb_block.c - Deal with GDB blocks
2 Copyright (C) 1987 Free Software Foundation, Inc.
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /*
21 * Implements .gdbblk, .gdbbeg, .gdbend concepts.
22 * No other modules need to know the details of these concepts.
23 *
24 * During assembly, note the addresses of block beginnings and ends.
25 * Each block has a begin-address, an end-address, a number, and
26 * a place in the GDB symbol file to place the 2 addresses.
27 * Block numbers are 0, 1, ... with no gaps.
28 *
29 * During assembly, we don't actually know the addresses, so they are
30 * expressed as {frag-address + offset-in-frag}.
31 *
32 * gdb_block_begin ()
33 * Call once before using this package.
34 *
35 * gdb_block_beg (number, frag, offset)
36 * Note a block beginning.
37 *
38 * gdb_block_end (number, frag, offset)
39 * Note a block end.
40 *
41 * gdb_block_position (block_number, pos)
42 * Remember, after assembly, to copy a structure containing
43 * the beginning and ending addresses of block number
44 * block_number into the gdb file, starting at position pos.
45 *
46 * gdb_block_emit (block_number, where_in_gdb_symbol_file)
47 * Emit a block begin/end locations to a place in the GDB symbol
48 * file.
49 *
50 * uses:
51 * xmalloc()
52 * gdb_alter()
53 */
54
55
56 #include "as.h"
57 \f
58 /*
59 * malloc() calls are considered expensive. So ...
60 *
61 * We remember blocks by making a tree, and each block number has a leaf.
62 * The tree is 3 levels, and we don't allocate interior nodes until they
63 * are needed. Both leaves and interior nodes are allocated in lumps,
64 * which should save on malloc() calls. Due to the way we break up a
65 * block number to navigate through the tree, we insist that lumps of
66 * memory contain a power of 2 items each. Powers of 2 may differ
67 * for different levels of tree.
68 */
69
70 /*
71 * A block number:
72 *
73 * +---------------+---------------+---------------+
74 * | | | |
75 * | Z2-part bits | Z1-part bits | Z0-part bits |
76 * | | | |
77 * +---------------+---------------+---------------+
78 *
79 * High order Low order
80 *
81 * "Z" is short for "siZe".
82 */
83
84 #define LOG_2_Z0 (8) /* How many bits are in Z0 part? */
85 #define LOG_2_Z1 (8) /* How many bits are in Z1 part? */
86 #define LOG_2_Z2 (8) /* How many bits are in Z2 part? */
87
88 #define BLOCK_NUMBER_LIMIT (1 << (LOG_2_Z0 + LOG_2_Z1 + LOG_2_Z2))
89 /* What is the first block number that is */
90 /* "too big"? */
91
92 struct gdb_block
93 {
94 fragS * begin_frag;
95 fragS * end_frag;
96 long int begin_where_in_frag;
97 long int end_where_in_frag;
98 long int position; /* In GDB symbols file. */
99 };
100
101 typedef struct gdb_block node_0_T [1 << LOG_2_Z0];
102
103 typedef node_0_T * node_1_T [1 << LOG_2_Z1];
104
105 typedef node_1_T * node_2_T [1 << LOG_2_Z2];
106
107
108 static long int highest_block_number_seen;
109 static node_2_T * root; /* 3 level tree of block locations. */
110
111 static node_2_T * new_2 ();
112
113
114 char * xmalloc();
115 void gdb_alter();
116 \f
117 void
118 gdb_block_begin ()
119 {
120 root = new_2 ();
121 highest_block_number_seen = -1;
122 }
123
124 static node_0_T *
125 new_0 ()
126 {
127 register node_0_T * place;
128
129 place = (node_0_T *) xmalloc ((long)sizeof(node_0_T));
130 bzero ((char *)place, sizeof(node_0_T));
131 return (place);
132 }
133
134 static node_1_T *
135 new_1 ()
136 {
137 register node_1_T * place;
138
139 place = (node_1_T *) xmalloc ((long)sizeof(node_1_T));
140 bzero ((char *)place, sizeof(node_1_T));
141 return (place);
142 }
143
144 static node_2_T *
145 new_2 ()
146 {
147 register node_2_T * place;
148
149 place = (node_2_T *) xmalloc ((long)sizeof(node_2_T));
150 bzero ((char *)place, sizeof(node_2_T));
151 return (place);
152 }
153 \f
154 static struct gdb_block *
155 find (block_number)
156 register long int block_number;
157 {
158 register node_1_T ** pp_1;
159 register node_0_T ** pp_0;
160 register struct gdb_block * b;
161 register int index0;
162 register int index1;
163 register int index2;
164
165 #ifdef SUSPECT
166 if (block_number >= BLOCK_NUMBER_LIMIT)
167 {
168 as_fatal ("gdb_block: Block number = %ld.", block_number);
169 }
170 #endif
171
172 index2 = block_number >> (LOG_2_Z0 + LOG_2_Z1);
173 index1 = block_number >> (LOG_2_Z0) & ((1 << LOG_2_Z1) - 1);
174 index0 = block_number & ((1 << LOG_2_Z0) - 1);
175 pp_1 = * root + index2;
176 if (* pp_1 == 0)
177 {
178 * pp_1 = new_1 ();
179 }
180 pp_0 = ** pp_1 + index1;
181 if (* pp_0 == 0)
182 {
183 * pp_0 = new_0 ();
184 }
185 b = ** pp_0 + index0;
186 return (b);
187 }
188
189
190 static struct gdb_block *
191 find_create (block_number)
192 long int block_number;
193 {
194 if (highest_block_number_seen < block_number)
195 {
196 highest_block_number_seen = block_number;
197 }
198 return (find (block_number));
199 }
200 \f
201 void
202 gdb_block_beg (block_number, frag, offset)
203 long int block_number;
204 fragS * frag;
205 long int offset;
206 {
207 struct gdb_block * pointer;
208
209 pointer = find_create (block_number);
210 #ifdef SUSPECT
211 if (pointer -> begin_frag != 0)
212 {
213 as_warn( "Overwriting begin_frag for block # %ld.", block_number );
214 }
215 if (pointer -> begin_where_in_frag != 0)
216 {
217 as_warn( "Overwriting begin_where_in_frag for block # %ld.", block_number );
218 }
219 #endif
220 pointer -> begin_frag = frag;
221 pointer -> begin_where_in_frag = offset;
222 }
223
224 void
225 gdb_block_end (block_number, frag, offset)
226 long int block_number;
227 fragS * frag;
228 long int offset;
229 {
230 struct gdb_block * pointer;
231
232 pointer = find_create (block_number);
233 #ifdef SUSPECT
234 if (pointer -> end_frag != 0)
235 {
236 as_warn( "Overwriting end_frag for block # %ld.", block_number );
237 }
238 if (pointer -> end_where_in_frag != 0)
239 {
240 as_warn( "Overwriting end_where_in_frag for block # %ld.", block_number );
241 }
242 #endif
243 pointer -> end_frag = frag;
244 pointer -> end_where_in_frag = offset;
245 }
246 \f
247 void
248 gdb_block_position (block_number, pos)
249 long int block_number;
250 long int pos;
251 {
252 struct gdb_block * pointer;
253
254 pointer = find_create (block_number);
255 if (pointer -> position != 0)
256 {
257 as_warn( "Overwriting old position %ld. in block #%ld.",
258 pointer -> position, block_number);
259 }
260 pointer -> position = pos;
261 }
262
263 void
264 gdb_block_emit ()
265 {
266 long int block_number;
267 struct gdb_block * b;
268
269 for (block_number = 0;
270 block_number <= highest_block_number_seen;
271 block_number ++)
272 {
273 b = find (block_number);
274 if (b -> begin_frag)
275 {
276 gdb_alter (b -> position,
277 (long int)
278 (b -> begin_frag -> fr_address + b -> begin_where_in_frag));
279 }
280 if (b -> end_frag)
281 {
282 gdb_alter (b -> position + sizeof( long int ),
283 (long int)
284 (b -> end_frag -> fr_address + b -> end_where_in_frag));
285 }
286 }
287 }
288
289 /* end: gdb_block.c */
This page took 0.037552 seconds and 4 git commands to generate.