gdb/testsuite: fix gdb.trace/signal.exp on x86
[binutils-gdb/blckswan.git] / gdb / addrmap.c
blob8141337e48445b84bd24fab1ca69aa82abb0bbb8
1 /* addrmap.c --- implementation of address map data structure.
3 Copyright (C) 2007-2022 Free Software Foundation, Inc.
5 This file is part of GDB.
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
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
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.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 #include "defs.h"
21 #include "splay-tree.h"
22 #include "gdbsupport/gdb_obstack.h"
23 #include "addrmap.h"
24 #include "gdbsupport/selftest.h"
26 /* Make sure splay trees can actually hold the values we want to
27 store in them. */
28 gdb_static_assert (sizeof (splay_tree_key) >= sizeof (CORE_ADDR *));
29 gdb_static_assert (sizeof (splay_tree_value) >= sizeof (void *));
32 /* The "abstract class". */
34 /* Functions implementing the addrmap functions for a particular
35 implementation. */
36 struct addrmap_funcs
38 void (*set_empty) (struct addrmap *self,
39 CORE_ADDR start, CORE_ADDR end_inclusive,
40 void *obj);
41 void *(*find) (const addrmap *self, CORE_ADDR addr);
42 struct addrmap *(*create_fixed) (struct addrmap *self,
43 struct obstack *obstack);
44 void (*relocate) (struct addrmap *self, CORE_ADDR offset);
45 int (*foreach) (struct addrmap *self, addrmap_foreach_fn fn);
49 struct addrmap
51 const struct addrmap_funcs *funcs;
55 void
56 addrmap_set_empty (struct addrmap *map,
57 CORE_ADDR start, CORE_ADDR end_inclusive,
58 void *obj)
60 map->funcs->set_empty (map, start, end_inclusive, obj);
64 void *
65 addrmap_find (const addrmap *map, CORE_ADDR addr)
67 return map->funcs->find (map, addr);
71 struct addrmap *
72 addrmap_create_fixed (struct addrmap *original, struct obstack *obstack)
74 return original->funcs->create_fixed (original, obstack);
78 /* Relocate all the addresses in MAP by OFFSET. (This can be applied
79 to either mutable or immutable maps.) */
80 void
81 addrmap_relocate (struct addrmap *map, CORE_ADDR offset)
83 map->funcs->relocate (map, offset);
87 int
88 addrmap_foreach (struct addrmap *map, addrmap_foreach_fn fn)
90 return map->funcs->foreach (map, fn);
93 /* Fixed address maps. */
95 /* A transition: a point in an address map where the value changes.
96 The map maps ADDR to VALUE, but if ADDR > 0, it maps ADDR-1 to
97 something else. */
98 struct addrmap_transition
100 CORE_ADDR addr;
101 void *value;
105 struct addrmap_fixed
107 struct addrmap addrmap;
109 /* The number of transitions in TRANSITIONS. */
110 size_t num_transitions;
112 /* An array of transitions, sorted by address. For every point in
113 the map where either ADDR == 0 or ADDR is mapped to one value and
114 ADDR - 1 is mapped to something different, we have an entry here
115 containing ADDR and VALUE. (Note that this means we always have
116 an entry for address 0). */
117 struct addrmap_transition transitions[1];
121 static void
122 addrmap_fixed_set_empty (struct addrmap *self,
123 CORE_ADDR start, CORE_ADDR end_inclusive,
124 void *obj)
126 internal_error (__FILE__, __LINE__,
127 "addrmap_fixed_set_empty: "
128 "fixed addrmaps can't be changed\n");
132 static void *
133 addrmap_fixed_find (const addrmap *self, CORE_ADDR addr)
135 const addrmap_fixed *map = (const addrmap_fixed *) self;
136 const addrmap_transition *bottom = &map->transitions[0];
137 const addrmap_transition *top = &map->transitions[map->num_transitions - 1];
139 while (bottom < top)
141 /* This needs to round towards top, or else when top = bottom +
142 1 (i.e., two entries are under consideration), then mid ==
143 bottom, and then we may not narrow the range when (mid->addr
144 < addr). */
145 const addrmap_transition *mid = top - (top - bottom) / 2;
147 if (mid->addr == addr)
149 bottom = mid;
150 break;
152 else if (mid->addr < addr)
153 /* We don't eliminate mid itself here, since each transition
154 covers all subsequent addresses until the next. This is why
155 we must round up in computing the midpoint. */
156 bottom = mid;
157 else
158 top = mid - 1;
161 return bottom->value;
165 static struct addrmap *
166 addrmap_fixed_create_fixed (struct addrmap *self, struct obstack *obstack)
168 internal_error (__FILE__, __LINE__,
169 _("addrmap_create_fixed is not implemented yet "
170 "for fixed addrmaps"));
174 static void
175 addrmap_fixed_relocate (struct addrmap *self, CORE_ADDR offset)
177 struct addrmap_fixed *map = (struct addrmap_fixed *) self;
178 size_t i;
180 for (i = 0; i < map->num_transitions; i++)
181 map->transitions[i].addr += offset;
185 static int
186 addrmap_fixed_foreach (struct addrmap *self, addrmap_foreach_fn fn)
188 struct addrmap_fixed *map = (struct addrmap_fixed *) self;
189 size_t i;
191 for (i = 0; i < map->num_transitions; i++)
193 int res = fn (map->transitions[i].addr, map->transitions[i].value);
195 if (res != 0)
196 return res;
199 return 0;
203 static const struct addrmap_funcs addrmap_fixed_funcs =
205 addrmap_fixed_set_empty,
206 addrmap_fixed_find,
207 addrmap_fixed_create_fixed,
208 addrmap_fixed_relocate,
209 addrmap_fixed_foreach
214 /* Mutable address maps. */
216 struct addrmap_mutable
218 struct addrmap addrmap;
220 /* The obstack to use for allocations for this map. */
221 struct obstack *obstack;
223 /* A splay tree, with a node for each transition; there is a
224 transition at address T if T-1 and T map to different objects.
226 Any addresses below the first node map to NULL. (Unlike
227 fixed maps, we have no entry at (CORE_ADDR) 0; it doesn't
228 simplify enough.)
230 The last region is assumed to end at CORE_ADDR_MAX.
232 Since we can't know whether CORE_ADDR is larger or smaller than
233 splay_tree_key (unsigned long) --- I think both are possible,
234 given all combinations of 32- and 64-bit hosts and targets ---
235 our keys are pointers to CORE_ADDR values. Since the splay tree
236 library doesn't pass any closure pointer to the key free
237 function, we can't keep a freelist for keys. Since mutable
238 addrmaps are only used temporarily right now, we just leak keys
239 from deleted nodes; they'll be freed when the obstack is freed. */
240 splay_tree tree;
242 /* A freelist for splay tree nodes, allocated on obstack, and
243 chained together by their 'right' pointers. */
244 splay_tree_node free_nodes;
248 /* Allocate a copy of CORE_ADDR in MAP's obstack. */
249 static splay_tree_key
250 allocate_key (struct addrmap_mutable *map, CORE_ADDR addr)
252 CORE_ADDR *key = XOBNEW (map->obstack, CORE_ADDR);
254 *key = addr;
255 return (splay_tree_key) key;
259 /* Type-correct wrappers for splay tree access. */
260 static splay_tree_node
261 addrmap_splay_tree_lookup (struct addrmap_mutable *map, CORE_ADDR addr)
263 return splay_tree_lookup (map->tree, (splay_tree_key) &addr);
267 static splay_tree_node
268 addrmap_splay_tree_predecessor (struct addrmap_mutable *map, CORE_ADDR addr)
270 return splay_tree_predecessor (map->tree, (splay_tree_key) &addr);
274 static splay_tree_node
275 addrmap_splay_tree_successor (struct addrmap_mutable *map, CORE_ADDR addr)
277 return splay_tree_successor (map->tree, (splay_tree_key) &addr);
281 static void
282 addrmap_splay_tree_remove (struct addrmap_mutable *map, CORE_ADDR addr)
284 splay_tree_remove (map->tree, (splay_tree_key) &addr);
288 static CORE_ADDR
289 addrmap_node_key (splay_tree_node node)
291 return * (CORE_ADDR *) node->key;
295 static void *
296 addrmap_node_value (splay_tree_node node)
298 return (void *) node->value;
302 static void
303 addrmap_node_set_value (splay_tree_node node, void *value)
305 node->value = (splay_tree_value) value;
309 static void
310 addrmap_splay_tree_insert (struct addrmap_mutable *map,
311 CORE_ADDR key, void *value)
313 splay_tree_insert (map->tree,
314 allocate_key (map, key),
315 (splay_tree_value) value);
319 /* Without changing the mapping of any address, ensure that there is a
320 tree node at ADDR, even if it would represent a "transition" from
321 one value to the same value. */
322 static void
323 force_transition (struct addrmap_mutable *self, CORE_ADDR addr)
325 splay_tree_node n
326 = addrmap_splay_tree_lookup (self, addr);
328 if (! n)
330 n = addrmap_splay_tree_predecessor (self, addr);
331 addrmap_splay_tree_insert (self, addr,
332 n ? addrmap_node_value (n) : NULL);
337 static void
338 addrmap_mutable_set_empty (struct addrmap *self,
339 CORE_ADDR start, CORE_ADDR end_inclusive,
340 void *obj)
342 struct addrmap_mutable *map = (struct addrmap_mutable *) self;
343 splay_tree_node n, next;
344 void *prior_value;
346 /* If we're being asked to set all empty portions of the given
347 address range to empty, then probably the caller is confused.
348 (If that turns out to be useful in some cases, then we can change
349 this to simply return, since overriding NULL with NULL is a
350 no-op.) */
351 gdb_assert (obj);
353 /* We take a two-pass approach, for simplicity.
354 - Establish transitions where we think we might need them.
355 - First pass: change all NULL regions to OBJ.
356 - Second pass: remove any unnecessary transitions. */
358 /* Establish transitions at the start and end. */
359 force_transition (map, start);
360 if (end_inclusive < CORE_ADDR_MAX)
361 force_transition (map, end_inclusive + 1);
363 /* Walk the area, changing all NULL regions to OBJ. */
364 for (n = addrmap_splay_tree_lookup (map, start), gdb_assert (n);
365 n && addrmap_node_key (n) <= end_inclusive;
366 n = addrmap_splay_tree_successor (map, addrmap_node_key (n)))
368 if (! addrmap_node_value (n))
369 addrmap_node_set_value (n, obj);
372 /* Walk the area again, removing transitions from any value to
373 itself. Be sure to visit both the transitions we forced
374 above. */
375 n = addrmap_splay_tree_predecessor (map, start);
376 prior_value = n ? addrmap_node_value (n) : NULL;
377 for (n = addrmap_splay_tree_lookup (map, start), gdb_assert (n);
378 n && (end_inclusive == CORE_ADDR_MAX
379 || addrmap_node_key (n) <= end_inclusive + 1);
380 n = next)
382 next = addrmap_splay_tree_successor (map, addrmap_node_key (n));
383 if (addrmap_node_value (n) == prior_value)
384 addrmap_splay_tree_remove (map, addrmap_node_key (n));
385 else
386 prior_value = addrmap_node_value (n);
391 static void *
392 addrmap_mutable_find (const addrmap *self, CORE_ADDR addr)
394 struct addrmap_mutable *map = (struct addrmap_mutable *) self;
395 splay_tree_node n = addrmap_splay_tree_lookup (map, addr);
396 if (n != nullptr)
398 gdb_assert (addrmap_node_key (n) == addr);
399 return addrmap_node_value (n);
402 n = addrmap_splay_tree_predecessor (map, addr);
403 if (n != nullptr)
405 gdb_assert (addrmap_node_key (n) < addr);
406 return addrmap_node_value (n);
409 return nullptr;
413 /* A function to pass to splay_tree_foreach to count the number of nodes
414 in the tree. */
415 static int
416 splay_foreach_count (splay_tree_node n, void *closure)
418 size_t *count = (size_t *) closure;
420 (*count)++;
421 return 0;
425 /* A function to pass to splay_tree_foreach to copy entries into a
426 fixed address map. */
427 static int
428 splay_foreach_copy (splay_tree_node n, void *closure)
430 struct addrmap_fixed *fixed = (struct addrmap_fixed *) closure;
431 struct addrmap_transition *t = &fixed->transitions[fixed->num_transitions];
433 t->addr = addrmap_node_key (n);
434 t->value = addrmap_node_value (n);
435 fixed->num_transitions++;
437 return 0;
441 static struct addrmap *
442 addrmap_mutable_create_fixed (struct addrmap *self, struct obstack *obstack)
444 struct addrmap_mutable *mutable_obj = (struct addrmap_mutable *) self;
445 struct addrmap_fixed *fixed;
446 size_t num_transitions;
447 size_t alloc_len;
449 /* Count the number of transitions in the tree. */
450 num_transitions = 0;
451 splay_tree_foreach (mutable_obj->tree, splay_foreach_count, &num_transitions);
453 /* Include an extra entry for the transition at zero (which fixed
454 maps have, but mutable maps do not.) */
455 num_transitions++;
457 alloc_len = sizeof (*fixed)
458 + (num_transitions * sizeof (fixed->transitions[0]));
459 fixed = (struct addrmap_fixed *) obstack_alloc (obstack, alloc_len);
460 fixed->addrmap.funcs = &addrmap_fixed_funcs;
461 fixed->num_transitions = 1;
462 fixed->transitions[0].addr = 0;
463 fixed->transitions[0].value = NULL;
465 /* Copy all entries from the splay tree to the array, in order
466 of increasing address. */
467 splay_tree_foreach (mutable_obj->tree, splay_foreach_copy, fixed);
469 /* We should have filled the array. */
470 gdb_assert (fixed->num_transitions == num_transitions);
472 return (struct addrmap *) fixed;
476 static void
477 addrmap_mutable_relocate (struct addrmap *self, CORE_ADDR offset)
479 /* Not needed yet. */
480 internal_error (__FILE__, __LINE__,
481 _("addrmap_relocate is not implemented yet "
482 "for mutable addrmaps"));
486 /* This is a splay_tree_foreach_fn. */
488 static int
489 addrmap_mutable_foreach_worker (splay_tree_node node, void *data)
491 addrmap_foreach_fn *fn = (addrmap_foreach_fn *) data;
493 return (*fn) (addrmap_node_key (node), addrmap_node_value (node));
497 static int
498 addrmap_mutable_foreach (struct addrmap *self, addrmap_foreach_fn fn)
500 struct addrmap_mutable *mutable_obj = (struct addrmap_mutable *) self;
502 return splay_tree_foreach (mutable_obj->tree, addrmap_mutable_foreach_worker,
503 &fn);
507 static const struct addrmap_funcs addrmap_mutable_funcs =
509 addrmap_mutable_set_empty,
510 addrmap_mutable_find,
511 addrmap_mutable_create_fixed,
512 addrmap_mutable_relocate,
513 addrmap_mutable_foreach
517 static void *
518 splay_obstack_alloc (int size, void *closure)
520 struct addrmap_mutable *map = (struct addrmap_mutable *) closure;
521 splay_tree_node n;
523 /* We should only be asked to allocate nodes and larger things.
524 (If, at some point in the future, this is no longer true, we can
525 just round up the size to sizeof (*n).) */
526 gdb_assert (size >= sizeof (*n));
528 if (map->free_nodes)
530 n = map->free_nodes;
531 map->free_nodes = n->right;
532 return n;
534 else
535 return obstack_alloc (map->obstack, size);
539 static void
540 splay_obstack_free (void *obj, void *closure)
542 struct addrmap_mutable *map = (struct addrmap_mutable *) closure;
543 splay_tree_node n = (splay_tree_node) obj;
545 /* We've asserted in the allocation function that we only allocate
546 nodes or larger things, so it should be safe to put whatever
547 we get passed back on the free list. */
548 n->right = map->free_nodes;
549 map->free_nodes = n;
553 /* Compare keys as CORE_ADDR * values. */
554 static int
555 splay_compare_CORE_ADDR_ptr (splay_tree_key ak, splay_tree_key bk)
557 CORE_ADDR a = * (CORE_ADDR *) ak;
558 CORE_ADDR b = * (CORE_ADDR *) bk;
560 /* We can't just return a-b here, because of over/underflow. */
561 if (a < b)
562 return -1;
563 else if (a == b)
564 return 0;
565 else
566 return 1;
570 struct addrmap *
571 addrmap_create_mutable (struct obstack *obstack)
573 struct addrmap_mutable *map = XOBNEW (obstack, struct addrmap_mutable);
575 map->addrmap.funcs = &addrmap_mutable_funcs;
576 map->obstack = obstack;
578 /* splay_tree_new_with_allocator uses the provided allocation
579 function to allocate the main splay_tree structure itself, so our
580 free list has to be initialized before we create the tree. */
581 map->free_nodes = NULL;
583 map->tree = splay_tree_new_with_allocator (splay_compare_CORE_ADDR_ptr,
584 NULL, /* no delete key */
585 NULL, /* no delete value */
586 splay_obstack_alloc,
587 splay_obstack_free,
588 map);
590 return (struct addrmap *) map;
593 /* See addrmap.h. */
595 void
596 addrmap_dump (struct addrmap *map, struct ui_file *outfile, void *payload)
598 /* True if the previously printed addrmap entry was for PAYLOAD.
599 If so, we want to print the next one as well (since the next
600 addrmap entry defines the end of the range). */
601 bool previous_matched = false;
603 auto callback = [&] (CORE_ADDR start_addr, void *obj)
605 QUIT;
607 bool matches = payload == nullptr || payload == obj;
608 const char *addr_str = nullptr;
609 if (matches)
610 addr_str = host_address_to_string (obj);
611 else if (previous_matched)
612 addr_str = "<ends here>";
614 if (matches || previous_matched)
615 gdb_printf (outfile, " %s%s %s\n",
616 payload != nullptr ? " " : "",
617 core_addr_to_string (start_addr),
618 addr_str);
620 previous_matched = matches;
622 return 0;
625 addrmap_foreach (map, callback);
628 #if GDB_SELF_TEST
629 namespace selftests {
631 /* Convert P to CORE_ADDR. */
633 static CORE_ADDR
634 core_addr (void *p)
636 return (CORE_ADDR)(uintptr_t)p;
639 /* Check that &ARRAY[LOW]..&ARRAY[HIGH] has VAL in MAP. */
641 #define CHECK_ADDRMAP_FIND(MAP, ARRAY, LOW, HIGH, VAL) \
642 do \
644 for (unsigned i = LOW; i <= HIGH; ++i) \
645 SELF_CHECK (addrmap_find (MAP, core_addr (&ARRAY[i])) == VAL); \
647 while (0)
649 /* Entry point for addrmap unit tests. */
651 static void
652 test_addrmap ()
654 /* We'll verify using the addresses of the elements of this array. */
655 char array[20];
657 /* We'll verify using these values stored into the map. */
658 void *val1 = &array[1];
659 void *val2 = &array[2];
661 /* Create mutable addrmap. */
662 struct obstack temp_obstack;
663 obstack_init (&temp_obstack);
664 struct addrmap *map = addrmap_create_mutable (&temp_obstack);
665 SELF_CHECK (map != nullptr);
667 /* Check initial state. */
668 CHECK_ADDRMAP_FIND (map, array, 0, 19, nullptr);
670 /* Insert address range into mutable addrmap. */
671 addrmap_set_empty (map, core_addr (&array[10]), core_addr (&array[12]),
672 val1);
673 CHECK_ADDRMAP_FIND (map, array, 0, 9, nullptr);
674 CHECK_ADDRMAP_FIND (map, array, 10, 12, val1);
675 CHECK_ADDRMAP_FIND (map, array, 13, 19, nullptr);
677 /* Create corresponding fixed addrmap. */
678 struct addrmap *map2 = addrmap_create_fixed (map, &temp_obstack);
679 SELF_CHECK (map2 != nullptr);
680 CHECK_ADDRMAP_FIND (map2, array, 0, 9, nullptr);
681 CHECK_ADDRMAP_FIND (map2, array, 10, 12, val1);
682 CHECK_ADDRMAP_FIND (map2, array, 13, 19, nullptr);
684 /* Iterate over both addrmaps. */
685 auto callback = [&] (CORE_ADDR start_addr, void *obj)
687 if (start_addr == core_addr (nullptr))
688 SELF_CHECK (obj == nullptr);
689 else if (start_addr == core_addr (&array[10]))
690 SELF_CHECK (obj == val1);
691 else if (start_addr == core_addr (&array[13]))
692 SELF_CHECK (obj == nullptr);
693 else
694 SELF_CHECK (false);
695 return 0;
697 SELF_CHECK (addrmap_foreach (map, callback) == 0);
698 SELF_CHECK (addrmap_foreach (map2, callback) == 0);
700 /* Relocate fixed addrmap. */
701 addrmap_relocate (map2, 1);
702 CHECK_ADDRMAP_FIND (map2, array, 0, 10, nullptr);
703 CHECK_ADDRMAP_FIND (map2, array, 11, 13, val1);
704 CHECK_ADDRMAP_FIND (map2, array, 14, 19, nullptr);
706 /* Insert partially overlapping address range into mutable addrmap. */
707 addrmap_set_empty (map, core_addr (&array[11]), core_addr (&array[13]),
708 val2);
709 CHECK_ADDRMAP_FIND (map, array, 0, 9, nullptr);
710 CHECK_ADDRMAP_FIND (map, array, 10, 12, val1);
711 CHECK_ADDRMAP_FIND (map, array, 13, 13, val2);
712 CHECK_ADDRMAP_FIND (map, array, 14, 19, nullptr);
714 /* Cleanup. */
715 obstack_free (&temp_obstack, NULL);
718 } // namespace selftests
719 #endif /* GDB_SELF_TEST */
721 void _initialize_addrmap ();
722 void
723 _initialize_addrmap ()
725 #if GDB_SELF_TEST
726 selftests::register_test ("addrmap", selftests::test_addrmap);
727 #endif /* GDB_SELF_TEST */