1 /* gdb_block.c - Deal with GDB blocks
2 Copyright (C) 1987 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
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)
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.
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. */
21 * Implements .gdbblk, .gdbbeg, .gdbend concepts.
22 * No other modules need to know the details of these concepts.
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.
29 * During assembly, we don't actually know the addresses, so they are
30 * expressed as {frag-address + offset-in-frag}.
33 * Call once before using this package.
35 * gdb_block_beg (number, frag, offset)
36 * Note a block beginning.
38 * gdb_block_end (number, frag, offset)
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.
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
59 * malloc() calls are considered expensive. So ...
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.
73 * +---------------+---------------+---------------+
75 * | Z2-part bits | Z1-part bits | Z0-part bits |
77 * +---------------+---------------+---------------+
79 * High order Low order
81 * "Z" is short for "siZe".
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? */
88 #define BLOCK_NUMBER_LIMIT (1 << (LOG_2_Z0 + LOG_2_Z1 + LOG_2_Z2))
89 /* What is the first block number that is */
96 long int begin_where_in_frag
;
97 long int end_where_in_frag
;
98 long int position
; /* In GDB symbols file. */
101 typedef struct gdb_block node_0_T
[1 << LOG_2_Z0
];
103 typedef node_0_T
* node_1_T
[1 << LOG_2_Z1
];
105 typedef node_1_T
* node_2_T
[1 << LOG_2_Z2
];
108 static long int highest_block_number_seen
;
109 static node_2_T
* root
; /* 3 level tree of block locations. */
111 static node_2_T
* new_2 ();
121 highest_block_number_seen
= -1;
127 register node_0_T
* place
;
129 place
= (node_0_T
*) xmalloc ((long)sizeof(node_0_T
));
130 bzero ((char *)place
, sizeof(node_0_T
));
137 register node_1_T
* place
;
139 place
= (node_1_T
*) xmalloc ((long)sizeof(node_1_T
));
140 bzero ((char *)place
, sizeof(node_1_T
));
147 register node_2_T
* place
;
149 place
= (node_2_T
*) xmalloc ((long)sizeof(node_2_T
));
150 bzero ((char *)place
, sizeof(node_2_T
));
154 static struct gdb_block
*
156 register long int block_number
;
158 register node_1_T
** pp_1
;
159 register node_0_T
** pp_0
;
160 register struct gdb_block
* b
;
166 if (block_number
>= BLOCK_NUMBER_LIMIT
)
168 as_fatal ("gdb_block: Block number = %ld.", block_number
);
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
;
180 pp_0
= ** pp_1
+ index1
;
185 b
= ** pp_0
+ index0
;
190 static struct gdb_block
*
191 find_create (block_number
)
192 long int block_number
;
194 if (highest_block_number_seen
< block_number
)
196 highest_block_number_seen
= block_number
;
198 return (find (block_number
));
202 gdb_block_beg (block_number
, frag
, offset
)
203 long int block_number
;
207 struct gdb_block
* pointer
;
209 pointer
= find_create (block_number
);
211 if (pointer
-> begin_frag
!= 0)
213 as_warn( "Overwriting begin_frag for block # %ld.", block_number
);
215 if (pointer
-> begin_where_in_frag
!= 0)
217 as_warn( "Overwriting begin_where_in_frag for block # %ld.", block_number
);
220 pointer
-> begin_frag
= frag
;
221 pointer
-> begin_where_in_frag
= offset
;
225 gdb_block_end (block_number
, frag
, offset
)
226 long int block_number
;
230 struct gdb_block
* pointer
;
232 pointer
= find_create (block_number
);
234 if (pointer
-> end_frag
!= 0)
236 as_warn( "Overwriting end_frag for block # %ld.", block_number
);
238 if (pointer
-> end_where_in_frag
!= 0)
240 as_warn( "Overwriting end_where_in_frag for block # %ld.", block_number
);
243 pointer
-> end_frag
= frag
;
244 pointer
-> end_where_in_frag
= offset
;
248 gdb_block_position (block_number
, pos
)
249 long int block_number
;
252 struct gdb_block
* pointer
;
254 pointer
= find_create (block_number
);
255 if (pointer
-> position
!= 0)
257 as_warn( "Overwriting old position %ld. in block #%ld.",
258 pointer
-> position
, block_number
);
260 pointer
-> position
= pos
;
266 long int block_number
;
267 struct gdb_block
* b
;
269 for (block_number
= 0;
270 block_number
<= highest_block_number_seen
;
273 b
= find (block_number
);
276 gdb_alter (b
-> position
,
278 (b
-> begin_frag
-> fr_address
+ b
-> begin_where_in_frag
));
282 gdb_alter (b
-> position
+ sizeof( long int ),
284 (b
-> end_frag
-> fr_address
+ b
-> end_where_in_frag
));
289 /* end: gdb_block.c */