Unify gdb printf functions
[binutils-gdb.git] / gdb / addrmap.c
1 /* addrmap.c --- implementation of address map data structure.
2
3 Copyright (C) 2007-2022 Free Software Foundation, Inc.
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
9 the Free Software Foundation; either version 3 of the License, or
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
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "defs.h"
21 #include "splay-tree.h"
22 #include "gdbsupport/gdb_obstack.h"
23 #include "addrmap.h"
24 #include "gdbsupport/selftest.h"
25
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 *));
30
31 \f
32 /* The "abstract class". */
33
34 /* Functions implementing the addrmap functions for a particular
35 implementation. */
36 struct addrmap_funcs
37 {
38 void (*set_empty) (struct addrmap *self,
39 CORE_ADDR start, CORE_ADDR end_inclusive,
40 void *obj);
41 void *(*find) (struct 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);
46 };
47
48
49 struct addrmap
50 {
51 const struct addrmap_funcs *funcs;
52 };
53
54
55 void
56 addrmap_set_empty (struct addrmap *map,
57 CORE_ADDR start, CORE_ADDR end_inclusive,
58 void *obj)
59 {
60 map->funcs->set_empty (map, start, end_inclusive, obj);
61 }
62
63
64 void *
65 addrmap_find (struct addrmap *map, CORE_ADDR addr)
66 {
67 return map->funcs->find (map, addr);
68 }
69
70
71 struct addrmap *
72 addrmap_create_fixed (struct addrmap *original, struct obstack *obstack)
73 {
74 return original->funcs->create_fixed (original, obstack);
75 }
76
77
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)
82 {
83 map->funcs->relocate (map, offset);
84 }
85
86
87 int
88 addrmap_foreach (struct addrmap *map, addrmap_foreach_fn fn)
89 {
90 return map->funcs->foreach (map, fn);
91 }
92 \f
93 /* Fixed address maps. */
94
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
99 {
100 CORE_ADDR addr;
101 void *value;
102 };
103
104
105 struct addrmap_fixed
106 {
107 struct addrmap addrmap;
108
109 /* The number of transitions in TRANSITIONS. */
110 size_t num_transitions;
111
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];
118 };
119
120
121 static void
122 addrmap_fixed_set_empty (struct addrmap *self,
123 CORE_ADDR start, CORE_ADDR end_inclusive,
124 void *obj)
125 {
126 internal_error (__FILE__, __LINE__,
127 "addrmap_fixed_set_empty: "
128 "fixed addrmaps can't be changed\n");
129 }
130
131
132 static void *
133 addrmap_fixed_find (struct addrmap *self, CORE_ADDR addr)
134 {
135 struct addrmap_fixed *map = (struct addrmap_fixed *) self;
136 struct addrmap_transition *bottom = &map->transitions[0];
137 struct addrmap_transition *top = &map->transitions[map->num_transitions - 1];
138
139 while (bottom < top)
140 {
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 struct addrmap_transition *mid = top - (top - bottom) / 2;
146
147 if (mid->addr == addr)
148 {
149 bottom = mid;
150 break;
151 }
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;
159 }
160
161 return bottom->value;
162 }
163
164
165 static struct addrmap *
166 addrmap_fixed_create_fixed (struct addrmap *self, struct obstack *obstack)
167 {
168 internal_error (__FILE__, __LINE__,
169 _("addrmap_create_fixed is not implemented yet "
170 "for fixed addrmaps"));
171 }
172
173
174 static void
175 addrmap_fixed_relocate (struct addrmap *self, CORE_ADDR offset)
176 {
177 struct addrmap_fixed *map = (struct addrmap_fixed *) self;
178 size_t i;
179
180 for (i = 0; i < map->num_transitions; i++)
181 map->transitions[i].addr += offset;
182 }
183
184
185 static int
186 addrmap_fixed_foreach (struct addrmap *self, addrmap_foreach_fn fn)
187 {
188 struct addrmap_fixed *map = (struct addrmap_fixed *) self;
189 size_t i;
190
191 for (i = 0; i < map->num_transitions; i++)
192 {
193 int res = fn (map->transitions[i].addr, map->transitions[i].value);
194
195 if (res != 0)
196 return res;
197 }
198
199 return 0;
200 }
201
202
203 static const struct addrmap_funcs addrmap_fixed_funcs =
204 {
205 addrmap_fixed_set_empty,
206 addrmap_fixed_find,
207 addrmap_fixed_create_fixed,
208 addrmap_fixed_relocate,
209 addrmap_fixed_foreach
210 };
211
212
213 \f
214 /* Mutable address maps. */
215
216 struct addrmap_mutable
217 {
218 struct addrmap addrmap;
219
220 /* The obstack to use for allocations for this map. */
221 struct obstack *obstack;
222
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.
225
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.)
229
230 The last region is assumed to end at CORE_ADDR_MAX.
231
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;
241
242 /* A freelist for splay tree nodes, allocated on obstack, and
243 chained together by their 'right' pointers. */
244 splay_tree_node free_nodes;
245 };
246
247
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)
251 {
252 CORE_ADDR *key = XOBNEW (map->obstack, CORE_ADDR);
253
254 *key = addr;
255 return (splay_tree_key) key;
256 }
257
258
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)
262 {
263 return splay_tree_lookup (map->tree, (splay_tree_key) &addr);
264 }
265
266
267 static splay_tree_node
268 addrmap_splay_tree_predecessor (struct addrmap_mutable *map, CORE_ADDR addr)
269 {
270 return splay_tree_predecessor (map->tree, (splay_tree_key) &addr);
271 }
272
273
274 static splay_tree_node
275 addrmap_splay_tree_successor (struct addrmap_mutable *map, CORE_ADDR addr)
276 {
277 return splay_tree_successor (map->tree, (splay_tree_key) &addr);
278 }
279
280
281 static void
282 addrmap_splay_tree_remove (struct addrmap_mutable *map, CORE_ADDR addr)
283 {
284 splay_tree_remove (map->tree, (splay_tree_key) &addr);
285 }
286
287
288 static CORE_ADDR
289 addrmap_node_key (splay_tree_node node)
290 {
291 return * (CORE_ADDR *) node->key;
292 }
293
294
295 static void *
296 addrmap_node_value (splay_tree_node node)
297 {
298 return (void *) node->value;
299 }
300
301
302 static void
303 addrmap_node_set_value (splay_tree_node node, void *value)
304 {
305 node->value = (splay_tree_value) value;
306 }
307
308
309 static void
310 addrmap_splay_tree_insert (struct addrmap_mutable *map,
311 CORE_ADDR key, void *value)
312 {
313 splay_tree_insert (map->tree,
314 allocate_key (map, key),
315 (splay_tree_value) value);
316 }
317
318
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)
324 {
325 splay_tree_node n
326 = addrmap_splay_tree_lookup (self, addr);
327
328 if (! n)
329 {
330 n = addrmap_splay_tree_predecessor (self, addr);
331 addrmap_splay_tree_insert (self, addr,
332 n ? addrmap_node_value (n) : NULL);
333 }
334 }
335
336
337 static void
338 addrmap_mutable_set_empty (struct addrmap *self,
339 CORE_ADDR start, CORE_ADDR end_inclusive,
340 void *obj)
341 {
342 struct addrmap_mutable *map = (struct addrmap_mutable *) self;
343 splay_tree_node n, next;
344 void *prior_value;
345
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);
352
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. */
357
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);
362
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)))
367 {
368 if (! addrmap_node_value (n))
369 addrmap_node_set_value (n, obj);
370 }
371
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)
381 {
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);
387 }
388 }
389
390
391 static void *
392 addrmap_mutable_find (struct addrmap *self, CORE_ADDR addr)
393 {
394 struct addrmap_mutable *map = (struct addrmap_mutable *) self;
395 splay_tree_node n = addrmap_splay_tree_lookup (map, addr);
396 if (n != nullptr)
397 {
398 gdb_assert (addrmap_node_key (n) == addr);
399 return addrmap_node_value (n);
400 }
401
402 n = addrmap_splay_tree_predecessor (map, addr);
403 if (n != nullptr)
404 {
405 gdb_assert (addrmap_node_key (n) < addr);
406 return addrmap_node_value (n);
407 }
408
409 return nullptr;
410 }
411
412
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)
417 {
418 size_t *count = (size_t *) closure;
419
420 (*count)++;
421 return 0;
422 }
423
424
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)
429 {
430 struct addrmap_fixed *fixed = (struct addrmap_fixed *) closure;
431 struct addrmap_transition *t = &fixed->transitions[fixed->num_transitions];
432
433 t->addr = addrmap_node_key (n);
434 t->value = addrmap_node_value (n);
435 fixed->num_transitions++;
436
437 return 0;
438 }
439
440
441 static struct addrmap *
442 addrmap_mutable_create_fixed (struct addrmap *self, struct obstack *obstack)
443 {
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;
448
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);
452
453 /* Include an extra entry for the transition at zero (which fixed
454 maps have, but mutable maps do not.) */
455 num_transitions++;
456
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;
464
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);
468
469 /* We should have filled the array. */
470 gdb_assert (fixed->num_transitions == num_transitions);
471
472 return (struct addrmap *) fixed;
473 }
474
475
476 static void
477 addrmap_mutable_relocate (struct addrmap *self, CORE_ADDR offset)
478 {
479 /* Not needed yet. */
480 internal_error (__FILE__, __LINE__,
481 _("addrmap_relocate is not implemented yet "
482 "for mutable addrmaps"));
483 }
484
485
486 /* This is a splay_tree_foreach_fn. */
487
488 static int
489 addrmap_mutable_foreach_worker (splay_tree_node node, void *data)
490 {
491 addrmap_foreach_fn *fn = (addrmap_foreach_fn *) data;
492
493 return (*fn) (addrmap_node_key (node), addrmap_node_value (node));
494 }
495
496
497 static int
498 addrmap_mutable_foreach (struct addrmap *self, addrmap_foreach_fn fn)
499 {
500 struct addrmap_mutable *mutable_obj = (struct addrmap_mutable *) self;
501
502 return splay_tree_foreach (mutable_obj->tree, addrmap_mutable_foreach_worker,
503 &fn);
504 }
505
506
507 static const struct addrmap_funcs addrmap_mutable_funcs =
508 {
509 addrmap_mutable_set_empty,
510 addrmap_mutable_find,
511 addrmap_mutable_create_fixed,
512 addrmap_mutable_relocate,
513 addrmap_mutable_foreach
514 };
515
516
517 static void *
518 splay_obstack_alloc (int size, void *closure)
519 {
520 struct addrmap_mutable *map = (struct addrmap_mutable *) closure;
521 splay_tree_node n;
522
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));
527
528 if (map->free_nodes)
529 {
530 n = map->free_nodes;
531 map->free_nodes = n->right;
532 return n;
533 }
534 else
535 return obstack_alloc (map->obstack, size);
536 }
537
538
539 static void
540 splay_obstack_free (void *obj, void *closure)
541 {
542 struct addrmap_mutable *map = (struct addrmap_mutable *) closure;
543 splay_tree_node n = (splay_tree_node) obj;
544
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;
550 }
551
552
553 /* Compare keys as CORE_ADDR * values. */
554 static int
555 splay_compare_CORE_ADDR_ptr (splay_tree_key ak, splay_tree_key bk)
556 {
557 CORE_ADDR a = * (CORE_ADDR *) ak;
558 CORE_ADDR b = * (CORE_ADDR *) bk;
559
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;
567 }
568
569
570 struct addrmap *
571 addrmap_create_mutable (struct obstack *obstack)
572 {
573 struct addrmap_mutable *map = XOBNEW (obstack, struct addrmap_mutable);
574
575 map->addrmap.funcs = &addrmap_mutable_funcs;
576 map->obstack = obstack;
577
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;
582
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);
589
590 return (struct addrmap *) map;
591 }
592
593 /* See addrmap.h. */
594
595 void
596 addrmap_dump (struct addrmap *map, struct ui_file *outfile, void *payload)
597 {
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;
602
603 auto callback = [&] (CORE_ADDR start_addr, void *obj)
604 {
605 QUIT;
606
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>";
613
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);
619
620 previous_matched = matches;
621
622 return 0;
623 };
624
625 addrmap_foreach (map, callback);
626 }
627
628 #if GDB_SELF_TEST
629 namespace selftests {
630
631 /* Convert P to CORE_ADDR. */
632
633 static CORE_ADDR
634 core_addr (void *p)
635 {
636 return (CORE_ADDR)(uintptr_t)p;
637 }
638
639 /* Check that &ARRAY[LOW]..&ARRAY[HIGH] has VAL in MAP. */
640
641 #define CHECK_ADDRMAP_FIND(MAP, ARRAY, LOW, HIGH, VAL) \
642 do \
643 { \
644 for (unsigned i = LOW; i <= HIGH; ++i) \
645 SELF_CHECK (addrmap_find (MAP, core_addr (&ARRAY[i])) == VAL); \
646 } \
647 while (0)
648
649 /* Entry point for addrmap unit tests. */
650
651 static void
652 test_addrmap ()
653 {
654 /* We'll verify using the addresses of the elements of this array. */
655 char array[20];
656
657 /* We'll verify using these values stored into the map. */
658 void *val1 = &array[1];
659 void *val2 = &array[2];
660
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);
666
667 /* Check initial state. */
668 CHECK_ADDRMAP_FIND (map, array, 0, 19, nullptr);
669
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);
676
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);
683
684 /* Iterate over both addrmaps. */
685 auto callback = [&] (CORE_ADDR start_addr, void *obj)
686 {
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;
696 };
697 SELF_CHECK (addrmap_foreach (map, callback) == 0);
698 SELF_CHECK (addrmap_foreach (map2, callback) == 0);
699
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);
705
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);
713
714 /* Cleanup. */
715 obstack_free (&temp_obstack, NULL);
716 }
717
718 } // namespace selftests
719 #endif /* GDB_SELF_TEST */
720
721 void _initialize_addrmap ();
722 void
723 _initialize_addrmap ()
724 {
725 #if GDB_SELF_TEST
726 selftests::register_test ("addrmap", selftests::test_addrmap);
727 #endif /* GDB_SELF_TEST */
728 }