Move stdlib.h to common-defs.h
[deliverable/binutils-gdb.git] / gdb / addrmap.c
CommitLineData
801e3a5b
JB
1/* addrmap.c --- implementation of address map data structure.
2
ecd75fc8 3 Copyright (C) 2007-2014 Free Software Foundation, Inc.
801e3a5b
JB
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
2fff4d11 9 the Free Software Foundation; either version 3 of the License, or
801e3a5b
JB
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
2fff4d11 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
801e3a5b
JB
19
20#include "defs.h"
801e3a5b
JB
21#include "splay-tree.h"
22#include "gdb_obstack.h"
23#include "addrmap.h"
24#include "gdb_assert.h"
25
26
27\f
28/* The "abstract class". */
29
30/* Functions implementing the addrmap functions for a particular
31 implementation. */
32struct addrmap_funcs
33{
34 void (*set_empty) (struct addrmap *this,
35 CORE_ADDR start, CORE_ADDR end_inclusive,
36 void *obj);
37 void *(*find) (struct addrmap *this, CORE_ADDR addr);
38 struct addrmap *(*create_fixed) (struct addrmap *this,
39 struct obstack *obstack);
40 void (*relocate) (struct addrmap *this, CORE_ADDR offset);
855c153f 41 int (*foreach) (struct addrmap *this, addrmap_foreach_fn fn, void *data);
801e3a5b
JB
42};
43
44
45struct addrmap
46{
2fff4d11 47 const struct addrmap_funcs *funcs;
801e3a5b
JB
48};
49
50
51void
52addrmap_set_empty (struct addrmap *map,
53 CORE_ADDR start, CORE_ADDR end_inclusive,
54 void *obj)
55{
56 map->funcs->set_empty (map, start, end_inclusive, obj);
57}
58
59
60void *
61addrmap_find (struct addrmap *map, CORE_ADDR addr)
62{
63 return map->funcs->find (map, addr);
64}
65
66
67struct addrmap *
68addrmap_create_fixed (struct addrmap *original, struct obstack *obstack)
69{
70 return original->funcs->create_fixed (original, obstack);
71}
72
73
74/* Relocate all the addresses in MAP by OFFSET. (This can be applied
75 to either mutable or immutable maps.) */
76void
77addrmap_relocate (struct addrmap *map, CORE_ADDR offset)
78{
79 map->funcs->relocate (map, offset);
80}
81
82
855c153f
DE
83int
84addrmap_foreach (struct addrmap *map, addrmap_foreach_fn fn, void *data)
85{
86 return map->funcs->foreach (map, fn, data);
87}
801e3a5b
JB
88\f
89/* Fixed address maps. */
90
91/* A transition: a point in an address map where the value changes.
92 The map maps ADDR to VALUE, but if ADDR > 0, it maps ADDR-1 to
93 something else. */
94struct addrmap_transition
95{
96 CORE_ADDR addr;
97 void *value;
98};
99
100
101struct addrmap_fixed
102{
103 struct addrmap addrmap;
104
105 /* The number of transitions in TRANSITIONS. */
106 size_t num_transitions;
107
108 /* An array of transitions, sorted by address. For every point in
109 the map where either ADDR == 0 or ADDR is mapped to one value and
110 ADDR - 1 is mapped to something different, we have an entry here
111 containing ADDR and VALUE. (Note that this means we always have
112 an entry for address 0). */
113 struct addrmap_transition transitions[1];
114};
115
116
117static void
118addrmap_fixed_set_empty (struct addrmap *this,
119 CORE_ADDR start, CORE_ADDR end_inclusive,
120 void *obj)
121{
122 internal_error (__FILE__, __LINE__,
123 "addrmap_fixed_set_empty: "
124 "fixed addrmaps can't be changed\n");
125}
126
127
128static void *
129addrmap_fixed_find (struct addrmap *this, CORE_ADDR addr)
130{
131 struct addrmap_fixed *map = (struct addrmap_fixed *) this;
132 struct addrmap_transition *bottom = &map->transitions[0];
133 struct addrmap_transition *top = &map->transitions[map->num_transitions - 1];
134
135 while (bottom < top)
136 {
137 /* This needs to round towards top, or else when top = bottom +
138 1 (i.e., two entries are under consideration), then mid ==
139 bottom, and then we may not narrow the range when (mid->addr
140 < addr). */
141 struct addrmap_transition *mid = top - (top - bottom) / 2;
142
143 if (mid->addr == addr)
144 {
145 bottom = mid;
146 break;
147 }
148 else if (mid->addr < addr)
149 /* We don't eliminate mid itself here, since each transition
150 covers all subsequent addresses until the next. This is why
151 we must round up in computing the midpoint. */
152 bottom = mid;
153 else
154 top = mid - 1;
155 }
156
157 return bottom->value;
158}
159
160
161static struct addrmap *
162addrmap_fixed_create_fixed (struct addrmap *this, struct obstack *obstack)
163{
2fff4d11
JB
164 internal_error (__FILE__, __LINE__,
165 _("addrmap_create_fixed is not implemented yet "
166 "for fixed addrmaps"));
801e3a5b
JB
167}
168
169
170static void
171addrmap_fixed_relocate (struct addrmap *this, CORE_ADDR offset)
172{
173 struct addrmap_fixed *map = (struct addrmap_fixed *) this;
174 size_t i;
175
176 for (i = 0; i < map->num_transitions; i++)
177 map->transitions[i].addr += offset;
178}
179
180
855c153f
DE
181static int
182addrmap_fixed_foreach (struct addrmap *this, addrmap_foreach_fn fn,
183 void *data)
184{
185 struct addrmap_fixed *map = (struct addrmap_fixed *) this;
186 size_t i;
187
188 for (i = 0; i < map->num_transitions; i++)
189 {
190 int res = fn (data, map->transitions[i].addr, map->transitions[i].value);
191
192 if (res != 0)
193 return res;
194 }
195
196 return 0;
197}
198
199
2fff4d11 200static const struct addrmap_funcs addrmap_fixed_funcs =
801e3a5b 201{
2fff4d11
JB
202 addrmap_fixed_set_empty,
203 addrmap_fixed_find,
204 addrmap_fixed_create_fixed,
855c153f
DE
205 addrmap_fixed_relocate,
206 addrmap_fixed_foreach
801e3a5b
JB
207};
208
209
210\f
211/* Mutable address maps. */
212
213struct addrmap_mutable
214{
215 struct addrmap addrmap;
216
217 /* The obstack to use for allocations for this map. */
218 struct obstack *obstack;
219
220 /* A splay tree, with a node for each transition; there is a
221 transition at address T if T-1 and T map to different objects.
222
223 Any addresses below the first node map to NULL. (Unlike
224 fixed maps, we have no entry at (CORE_ADDR) 0; it doesn't
225 simplify enough.)
226
227 The last region is assumed to end at CORE_ADDR_MAX.
228
229 Since we can't know whether CORE_ADDR is larger or smaller than
230 splay_tree_key (unsigned long) --- I think both are possible,
231 given all combinations of 32- and 64-bit hosts and targets ---
232 our keys are pointers to CORE_ADDR values. Since the splay tree
233 library doesn't pass any closure pointer to the key free
234 function, we can't keep a freelist for keys. Since mutable
235 addrmaps are only used temporarily right now, we just leak keys
236 from deleted nodes; they'll be freed when the obstack is freed. */
237 splay_tree tree;
238
239 /* A freelist for splay tree nodes, allocated on obstack, and
240 chained together by their 'right' pointers. */
241 splay_tree_node free_nodes;
242};
243
244
245/* Allocate a copy of CORE_ADDR in MAP's obstack. */
246static splay_tree_key
247allocate_key (struct addrmap_mutable *map, CORE_ADDR addr)
248{
249 CORE_ADDR *key = obstack_alloc (map->obstack, sizeof (*key));
801e3a5b 250
5b4ee69b 251 *key = addr;
801e3a5b
JB
252 return (splay_tree_key) key;
253}
254
255
256/* Type-correct wrappers for splay tree access. */
257static splay_tree_node
258addrmap_splay_tree_lookup (struct addrmap_mutable *map, CORE_ADDR addr)
259{
260 return splay_tree_lookup (map->tree, (splay_tree_key) &addr);
261}
262
263
264static splay_tree_node
265addrmap_splay_tree_predecessor (struct addrmap_mutable *map, CORE_ADDR addr)
266{
267 return splay_tree_predecessor (map->tree, (splay_tree_key) &addr);
268}
269
270
271static splay_tree_node
272addrmap_splay_tree_successor (struct addrmap_mutable *map, CORE_ADDR addr)
273{
274 return splay_tree_successor (map->tree, (splay_tree_key) &addr);
275}
276
277
cb446409
JB
278static void
279addrmap_splay_tree_remove (struct addrmap_mutable *map, CORE_ADDR addr)
280{
281 splay_tree_remove (map->tree, (splay_tree_key) &addr);
282}
283
284
801e3a5b
JB
285static CORE_ADDR
286addrmap_node_key (splay_tree_node node)
287{
288 return * (CORE_ADDR *) node->key;
289}
290
291
292static void *
293addrmap_node_value (splay_tree_node node)
294{
295 return (void *) node->value;
296}
297
298
299static void
300addrmap_node_set_value (splay_tree_node node, void *value)
301{
302 node->value = (splay_tree_value) value;
303}
304
305
306static void
3e43a32a
MS
307addrmap_splay_tree_insert (struct addrmap_mutable *map,
308 CORE_ADDR key, void *value)
801e3a5b
JB
309{
310 splay_tree_insert (map->tree,
311 allocate_key (map, key),
312 (splay_tree_value) value);
313}
314
315
316/* Without changing the mapping of any address, ensure that there is a
317 tree node at ADDR, even if it would represent a "transition" from
318 one value to the same value. */
319static void
320force_transition (struct addrmap_mutable *this, CORE_ADDR addr)
321{
322 splay_tree_node n
323 = addrmap_splay_tree_lookup (this, addr);
324
325 if (! n)
326 {
327 n = addrmap_splay_tree_predecessor (this, addr);
328 addrmap_splay_tree_insert (this, addr,
329 n ? addrmap_node_value (n) : NULL);
330 }
331}
332
333
334static void
335addrmap_mutable_set_empty (struct addrmap *this,
336 CORE_ADDR start, CORE_ADDR end_inclusive,
337 void *obj)
338{
339 struct addrmap_mutable *map = (struct addrmap_mutable *) this;
340 splay_tree_node n, next;
341 void *prior_value;
342
343 /* If we're being asked to set all empty portions of the given
344 address range to empty, then probably the caller is confused.
345 (If that turns out to be useful in some cases, then we can change
346 this to simply return, since overriding NULL with NULL is a
347 no-op.) */
348 gdb_assert (obj);
349
350 /* We take a two-pass approach, for simplicity.
351 - Establish transitions where we think we might need them.
352 - First pass: change all NULL regions to OBJ.
353 - Second pass: remove any unnecessary transitions. */
354
355 /* Establish transitions at the start and end. */
356 force_transition (map, start);
357 if (end_inclusive < CORE_ADDR_MAX)
358 force_transition (map, end_inclusive + 1);
359
360 /* Walk the area, changing all NULL regions to OBJ. */
361 for (n = addrmap_splay_tree_lookup (map, start), gdb_assert (n);
362 n && addrmap_node_key (n) <= end_inclusive;
363 n = addrmap_splay_tree_successor (map, addrmap_node_key (n)))
364 {
365 if (! addrmap_node_value (n))
366 addrmap_node_set_value (n, obj);
367 }
368
369 /* Walk the area again, removing transitions from any value to
370 itself. Be sure to visit both the transitions we forced
371 above. */
372 n = addrmap_splay_tree_predecessor (map, start);
373 prior_value = n ? addrmap_node_value (n) : NULL;
374 for (n = addrmap_splay_tree_lookup (map, start), gdb_assert (n);
375 n && (end_inclusive == CORE_ADDR_MAX
376 || addrmap_node_key (n) <= end_inclusive + 1);
377 n = next)
378 {
379 next = addrmap_splay_tree_successor (map, addrmap_node_key (n));
380 if (addrmap_node_value (n) == prior_value)
cb446409 381 addrmap_splay_tree_remove (map, addrmap_node_key (n));
801e3a5b
JB
382 else
383 prior_value = addrmap_node_value (n);
384 }
385}
386
387
388static void *
389addrmap_mutable_find (struct addrmap *this, CORE_ADDR addr)
390{
391 /* Not needed yet. */
2fff4d11
JB
392 internal_error (__FILE__, __LINE__,
393 _("addrmap_find is not implemented yet "
394 "for mutable addrmaps"));
801e3a5b
JB
395}
396
397
398/* A function to pass to splay_tree_foreach to count the number of nodes
399 in the tree. */
400static int
401splay_foreach_count (splay_tree_node n, void *closure)
402{
403 size_t *count = (size_t *) closure;
404
405 (*count)++;
406 return 0;
407}
408
409
410/* A function to pass to splay_tree_foreach to copy entries into a
411 fixed address map. */
412static int
413splay_foreach_copy (splay_tree_node n, void *closure)
414{
415 struct addrmap_fixed *fixed = (struct addrmap_fixed *) closure;
416 struct addrmap_transition *t = &fixed->transitions[fixed->num_transitions];
417
418 t->addr = addrmap_node_key (n);
419 t->value = addrmap_node_value (n);
420 fixed->num_transitions++;
421
422 return 0;
423}
424
425
426static struct addrmap *
427addrmap_mutable_create_fixed (struct addrmap *this, struct obstack *obstack)
428{
429 struct addrmap_mutable *mutable = (struct addrmap_mutable *) this;
430 struct addrmap_fixed *fixed;
431 size_t num_transitions;
432
433 /* Count the number of transitions in the tree. */
434 num_transitions = 0;
435 splay_tree_foreach (mutable->tree, splay_foreach_count, &num_transitions);
436
437 /* Include an extra entry for the transition at zero (which fixed
438 maps have, but mutable maps do not.) */
439 num_transitions++;
440
441 fixed = obstack_alloc (obstack,
442 (sizeof (*fixed)
443 + (num_transitions
444 * sizeof (fixed->transitions[0]))));
445 fixed->addrmap.funcs = &addrmap_fixed_funcs;
446 fixed->num_transitions = 1;
447 fixed->transitions[0].addr = 0;
448 fixed->transitions[0].value = NULL;
449
450 /* Copy all entries from the splay tree to the array, in order
451 of increasing address. */
452 splay_tree_foreach (mutable->tree, splay_foreach_copy, fixed);
453
454 /* We should have filled the array. */
455 gdb_assert (fixed->num_transitions == num_transitions);
456
457 return (struct addrmap *) fixed;
458}
459
460
461static void
462addrmap_mutable_relocate (struct addrmap *this, CORE_ADDR offset)
463{
464 /* Not needed yet. */
2fff4d11
JB
465 internal_error (__FILE__, __LINE__,
466 _("addrmap_relocate is not implemented yet "
467 "for mutable addrmaps"));
801e3a5b
JB
468}
469
470
855c153f
DE
471/* Struct to map addrmap's foreach function to splay_tree's version. */
472struct mutable_foreach_data
473{
474 addrmap_foreach_fn fn;
475 void *data;
476};
477
478
479/* This is a splay_tree_foreach_fn. */
480
481static int
482addrmap_mutable_foreach_worker (splay_tree_node node, void *data)
483{
484 struct mutable_foreach_data *foreach_data = data;
485
486 return foreach_data->fn (foreach_data->data,
487 addrmap_node_key (node),
488 addrmap_node_value (node));
489}
490
491
492static int
493addrmap_mutable_foreach (struct addrmap *this, addrmap_foreach_fn fn,
494 void *data)
495{
496 struct addrmap_mutable *mutable = (struct addrmap_mutable *) this;
497 struct mutable_foreach_data foreach_data;
498
499 foreach_data.fn = fn;
500 foreach_data.data = data;
501 return splay_tree_foreach (mutable->tree, addrmap_mutable_foreach_worker,
502 &foreach_data);
503}
504
505
2fff4d11 506static const struct addrmap_funcs addrmap_mutable_funcs =
801e3a5b 507{
2fff4d11
JB
508 addrmap_mutable_set_empty,
509 addrmap_mutable_find,
510 addrmap_mutable_create_fixed,
855c153f
DE
511 addrmap_mutable_relocate,
512 addrmap_mutable_foreach
801e3a5b
JB
513};
514
515
516static void *
517splay_obstack_alloc (int size, void *closure)
518{
519 struct addrmap_mutable *map = closure;
520 splay_tree_node n;
521
522 /* We should only be asked to allocate nodes and larger things.
523 (If, at some point in the future, this is no longer true, we can
524 just round up the size to sizeof (*n).) */
525 gdb_assert (size >= sizeof (*n));
526
527 if (map->free_nodes)
528 {
529 n = map->free_nodes;
530 map->free_nodes = n->right;
531 return n;
532 }
533 else
534 return obstack_alloc (map->obstack, size);
535}
536
537
538static void
539splay_obstack_free (void *obj, void *closure)
540{
541 struct addrmap_mutable *map = closure;
542 splay_tree_node n = obj;
543
544 /* We've asserted in the allocation function that we only allocate
545 nodes or larger things, so it should be safe to put whatever
546 we get passed back on the free list. */
547 n->right = map->free_nodes;
548 map->free_nodes = n;
549}
550
551
552/* Compare keys as CORE_ADDR * values. */
553static int
554splay_compare_CORE_ADDR_ptr (splay_tree_key ak, splay_tree_key bk)
555{
556 CORE_ADDR a = * (CORE_ADDR *) ak;
557 CORE_ADDR b = * (CORE_ADDR *) bk;
558
559 /* We can't just return a-b here, because of over/underflow. */
560 if (a < b)
561 return -1;
562 else if (a == b)
563 return 0;
564 else
565 return 1;
566}
567
568
569struct addrmap *
570addrmap_create_mutable (struct obstack *obstack)
571{
572 struct addrmap_mutable *map = obstack_alloc (obstack, sizeof (*map));
573
574 map->addrmap.funcs = &addrmap_mutable_funcs;
575 map->obstack = obstack;
576
577 /* splay_tree_new_with_allocator uses the provided allocation
578 function to allocate the main splay_tree structure itself, so our
579 free list has to be initialized before we create the tree. */
580 map->free_nodes = NULL;
581
582 map->tree = splay_tree_new_with_allocator (splay_compare_CORE_ADDR_ptr,
583 NULL, /* no delete key */
584 NULL, /* no delete value */
585 splay_obstack_alloc,
586 splay_obstack_free,
587 map);
588
589 return (struct addrmap *) map;
590}
591
592
593\f
594/* Initialization. */
595
2c0b251b
PA
596/* Provide a prototype to silence -Wmissing-prototypes. */
597extern initialize_file_ftype _initialize_addrmap;
598
801e3a5b
JB
599void
600_initialize_addrmap (void)
601{
602 /* Make sure splay trees can actually hold the values we want to
603 store in them. */
604 gdb_assert (sizeof (splay_tree_key) >= sizeof (CORE_ADDR *));
605 gdb_assert (sizeof (splay_tree_value) >= sizeof (void *));
606}
This page took 0.569223 seconds and 4 git commands to generate.