GDB (API)
|
00001 /* addrmap.c --- implementation of address map data structure. 00002 00003 Copyright (C) 2007-2013 Free Software Foundation, Inc. 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 #include "defs.h" 00021 00022 #include <stdlib.h> 00023 00024 #include "splay-tree.h" 00025 #include "gdb_obstack.h" 00026 #include "addrmap.h" 00027 #include "gdb_assert.h" 00028 00029 00030 00031 /* The "abstract class". */ 00032 00033 /* Functions implementing the addrmap functions for a particular 00034 implementation. */ 00035 struct addrmap_funcs 00036 { 00037 void (*set_empty) (struct addrmap *this, 00038 CORE_ADDR start, CORE_ADDR end_inclusive, 00039 void *obj); 00040 void *(*find) (struct addrmap *this, CORE_ADDR addr); 00041 struct addrmap *(*create_fixed) (struct addrmap *this, 00042 struct obstack *obstack); 00043 void (*relocate) (struct addrmap *this, CORE_ADDR offset); 00044 int (*foreach) (struct addrmap *this, addrmap_foreach_fn fn, void *data); 00045 }; 00046 00047 00048 struct addrmap 00049 { 00050 const struct addrmap_funcs *funcs; 00051 }; 00052 00053 00054 void 00055 addrmap_set_empty (struct addrmap *map, 00056 CORE_ADDR start, CORE_ADDR end_inclusive, 00057 void *obj) 00058 { 00059 map->funcs->set_empty (map, start, end_inclusive, obj); 00060 } 00061 00062 00063 void * 00064 addrmap_find (struct addrmap *map, CORE_ADDR addr) 00065 { 00066 return map->funcs->find (map, addr); 00067 } 00068 00069 00070 struct addrmap * 00071 addrmap_create_fixed (struct addrmap *original, struct obstack *obstack) 00072 { 00073 return original->funcs->create_fixed (original, obstack); 00074 } 00075 00076 00077 /* Relocate all the addresses in MAP by OFFSET. (This can be applied 00078 to either mutable or immutable maps.) */ 00079 void 00080 addrmap_relocate (struct addrmap *map, CORE_ADDR offset) 00081 { 00082 map->funcs->relocate (map, offset); 00083 } 00084 00085 00086 int 00087 addrmap_foreach (struct addrmap *map, addrmap_foreach_fn fn, void *data) 00088 { 00089 return map->funcs->foreach (map, fn, data); 00090 } 00091 00092 /* Fixed address maps. */ 00093 00094 /* A transition: a point in an address map where the value changes. 00095 The map maps ADDR to VALUE, but if ADDR > 0, it maps ADDR-1 to 00096 something else. */ 00097 struct addrmap_transition 00098 { 00099 CORE_ADDR addr; 00100 void *value; 00101 }; 00102 00103 00104 struct addrmap_fixed 00105 { 00106 struct addrmap addrmap; 00107 00108 /* The number of transitions in TRANSITIONS. */ 00109 size_t num_transitions; 00110 00111 /* An array of transitions, sorted by address. For every point in 00112 the map where either ADDR == 0 or ADDR is mapped to one value and 00113 ADDR - 1 is mapped to something different, we have an entry here 00114 containing ADDR and VALUE. (Note that this means we always have 00115 an entry for address 0). */ 00116 struct addrmap_transition transitions[1]; 00117 }; 00118 00119 00120 static void 00121 addrmap_fixed_set_empty (struct addrmap *this, 00122 CORE_ADDR start, CORE_ADDR end_inclusive, 00123 void *obj) 00124 { 00125 internal_error (__FILE__, __LINE__, 00126 "addrmap_fixed_set_empty: " 00127 "fixed addrmaps can't be changed\n"); 00128 } 00129 00130 00131 static void * 00132 addrmap_fixed_find (struct addrmap *this, CORE_ADDR addr) 00133 { 00134 struct addrmap_fixed *map = (struct addrmap_fixed *) this; 00135 struct addrmap_transition *bottom = &map->transitions[0]; 00136 struct addrmap_transition *top = &map->transitions[map->num_transitions - 1]; 00137 00138 while (bottom < top) 00139 { 00140 /* This needs to round towards top, or else when top = bottom + 00141 1 (i.e., two entries are under consideration), then mid == 00142 bottom, and then we may not narrow the range when (mid->addr 00143 < addr). */ 00144 struct addrmap_transition *mid = top - (top - bottom) / 2; 00145 00146 if (mid->addr == addr) 00147 { 00148 bottom = mid; 00149 break; 00150 } 00151 else if (mid->addr < addr) 00152 /* We don't eliminate mid itself here, since each transition 00153 covers all subsequent addresses until the next. This is why 00154 we must round up in computing the midpoint. */ 00155 bottom = mid; 00156 else 00157 top = mid - 1; 00158 } 00159 00160 return bottom->value; 00161 } 00162 00163 00164 static struct addrmap * 00165 addrmap_fixed_create_fixed (struct addrmap *this, struct obstack *obstack) 00166 { 00167 internal_error (__FILE__, __LINE__, 00168 _("addrmap_create_fixed is not implemented yet " 00169 "for fixed addrmaps")); 00170 } 00171 00172 00173 static void 00174 addrmap_fixed_relocate (struct addrmap *this, CORE_ADDR offset) 00175 { 00176 struct addrmap_fixed *map = (struct addrmap_fixed *) this; 00177 size_t i; 00178 00179 for (i = 0; i < map->num_transitions; i++) 00180 map->transitions[i].addr += offset; 00181 } 00182 00183 00184 static int 00185 addrmap_fixed_foreach (struct addrmap *this, addrmap_foreach_fn fn, 00186 void *data) 00187 { 00188 struct addrmap_fixed *map = (struct addrmap_fixed *) this; 00189 size_t i; 00190 00191 for (i = 0; i < map->num_transitions; i++) 00192 { 00193 int res = fn (data, map->transitions[i].addr, map->transitions[i].value); 00194 00195 if (res != 0) 00196 return res; 00197 } 00198 00199 return 0; 00200 } 00201 00202 00203 static const struct addrmap_funcs addrmap_fixed_funcs = 00204 { 00205 addrmap_fixed_set_empty, 00206 addrmap_fixed_find, 00207 addrmap_fixed_create_fixed, 00208 addrmap_fixed_relocate, 00209 addrmap_fixed_foreach 00210 }; 00211 00212 00213 00214 /* Mutable address maps. */ 00215 00216 struct addrmap_mutable 00217 { 00218 struct addrmap addrmap; 00219 00220 /* The obstack to use for allocations for this map. */ 00221 struct obstack *obstack; 00222 00223 /* A splay tree, with a node for each transition; there is a 00224 transition at address T if T-1 and T map to different objects. 00225 00226 Any addresses below the first node map to NULL. (Unlike 00227 fixed maps, we have no entry at (CORE_ADDR) 0; it doesn't 00228 simplify enough.) 00229 00230 The last region is assumed to end at CORE_ADDR_MAX. 00231 00232 Since we can't know whether CORE_ADDR is larger or smaller than 00233 splay_tree_key (unsigned long) --- I think both are possible, 00234 given all combinations of 32- and 64-bit hosts and targets --- 00235 our keys are pointers to CORE_ADDR values. Since the splay tree 00236 library doesn't pass any closure pointer to the key free 00237 function, we can't keep a freelist for keys. Since mutable 00238 addrmaps are only used temporarily right now, we just leak keys 00239 from deleted nodes; they'll be freed when the obstack is freed. */ 00240 splay_tree tree; 00241 00242 /* A freelist for splay tree nodes, allocated on obstack, and 00243 chained together by their 'right' pointers. */ 00244 splay_tree_node free_nodes; 00245 }; 00246 00247 00248 /* Allocate a copy of CORE_ADDR in MAP's obstack. */ 00249 static splay_tree_key 00250 allocate_key (struct addrmap_mutable *map, CORE_ADDR addr) 00251 { 00252 CORE_ADDR *key = obstack_alloc (map->obstack, sizeof (*key)); 00253 00254 *key = addr; 00255 return (splay_tree_key) key; 00256 } 00257 00258 00259 /* Type-correct wrappers for splay tree access. */ 00260 static splay_tree_node 00261 addrmap_splay_tree_lookup (struct addrmap_mutable *map, CORE_ADDR addr) 00262 { 00263 return splay_tree_lookup (map->tree, (splay_tree_key) &addr); 00264 } 00265 00266 00267 static splay_tree_node 00268 addrmap_splay_tree_predecessor (struct addrmap_mutable *map, CORE_ADDR addr) 00269 { 00270 return splay_tree_predecessor (map->tree, (splay_tree_key) &addr); 00271 } 00272 00273 00274 static splay_tree_node 00275 addrmap_splay_tree_successor (struct addrmap_mutable *map, CORE_ADDR addr) 00276 { 00277 return splay_tree_successor (map->tree, (splay_tree_key) &addr); 00278 } 00279 00280 00281 static void 00282 addrmap_splay_tree_remove (struct addrmap_mutable *map, CORE_ADDR addr) 00283 { 00284 splay_tree_remove (map->tree, (splay_tree_key) &addr); 00285 } 00286 00287 00288 static CORE_ADDR 00289 addrmap_node_key (splay_tree_node node) 00290 { 00291 return * (CORE_ADDR *) node->key; 00292 } 00293 00294 00295 static void * 00296 addrmap_node_value (splay_tree_node node) 00297 { 00298 return (void *) node->value; 00299 } 00300 00301 00302 static void 00303 addrmap_node_set_value (splay_tree_node node, void *value) 00304 { 00305 node->value = (splay_tree_value) value; 00306 } 00307 00308 00309 static void 00310 addrmap_splay_tree_insert (struct addrmap_mutable *map, 00311 CORE_ADDR key, void *value) 00312 { 00313 splay_tree_insert (map->tree, 00314 allocate_key (map, key), 00315 (splay_tree_value) value); 00316 } 00317 00318 00319 /* Without changing the mapping of any address, ensure that there is a 00320 tree node at ADDR, even if it would represent a "transition" from 00321 one value to the same value. */ 00322 static void 00323 force_transition (struct addrmap_mutable *this, CORE_ADDR addr) 00324 { 00325 splay_tree_node n 00326 = addrmap_splay_tree_lookup (this, addr); 00327 00328 if (! n) 00329 { 00330 n = addrmap_splay_tree_predecessor (this, addr); 00331 addrmap_splay_tree_insert (this, addr, 00332 n ? addrmap_node_value (n) : NULL); 00333 } 00334 } 00335 00336 00337 static void 00338 addrmap_mutable_set_empty (struct addrmap *this, 00339 CORE_ADDR start, CORE_ADDR end_inclusive, 00340 void *obj) 00341 { 00342 struct addrmap_mutable *map = (struct addrmap_mutable *) this; 00343 splay_tree_node n, next; 00344 void *prior_value; 00345 00346 /* If we're being asked to set all empty portions of the given 00347 address range to empty, then probably the caller is confused. 00348 (If that turns out to be useful in some cases, then we can change 00349 this to simply return, since overriding NULL with NULL is a 00350 no-op.) */ 00351 gdb_assert (obj); 00352 00353 /* We take a two-pass approach, for simplicity. 00354 - Establish transitions where we think we might need them. 00355 - First pass: change all NULL regions to OBJ. 00356 - Second pass: remove any unnecessary transitions. */ 00357 00358 /* Establish transitions at the start and end. */ 00359 force_transition (map, start); 00360 if (end_inclusive < CORE_ADDR_MAX) 00361 force_transition (map, end_inclusive + 1); 00362 00363 /* Walk the area, changing all NULL regions to OBJ. */ 00364 for (n = addrmap_splay_tree_lookup (map, start), gdb_assert (n); 00365 n && addrmap_node_key (n) <= end_inclusive; 00366 n = addrmap_splay_tree_successor (map, addrmap_node_key (n))) 00367 { 00368 if (! addrmap_node_value (n)) 00369 addrmap_node_set_value (n, obj); 00370 } 00371 00372 /* Walk the area again, removing transitions from any value to 00373 itself. Be sure to visit both the transitions we forced 00374 above. */ 00375 n = addrmap_splay_tree_predecessor (map, start); 00376 prior_value = n ? addrmap_node_value (n) : NULL; 00377 for (n = addrmap_splay_tree_lookup (map, start), gdb_assert (n); 00378 n && (end_inclusive == CORE_ADDR_MAX 00379 || addrmap_node_key (n) <= end_inclusive + 1); 00380 n = next) 00381 { 00382 next = addrmap_splay_tree_successor (map, addrmap_node_key (n)); 00383 if (addrmap_node_value (n) == prior_value) 00384 addrmap_splay_tree_remove (map, addrmap_node_key (n)); 00385 else 00386 prior_value = addrmap_node_value (n); 00387 } 00388 } 00389 00390 00391 static void * 00392 addrmap_mutable_find (struct addrmap *this, CORE_ADDR addr) 00393 { 00394 /* Not needed yet. */ 00395 internal_error (__FILE__, __LINE__, 00396 _("addrmap_find is not implemented yet " 00397 "for mutable addrmaps")); 00398 } 00399 00400 00401 /* A function to pass to splay_tree_foreach to count the number of nodes 00402 in the tree. */ 00403 static int 00404 splay_foreach_count (splay_tree_node n, void *closure) 00405 { 00406 size_t *count = (size_t *) closure; 00407 00408 (*count)++; 00409 return 0; 00410 } 00411 00412 00413 /* A function to pass to splay_tree_foreach to copy entries into a 00414 fixed address map. */ 00415 static int 00416 splay_foreach_copy (splay_tree_node n, void *closure) 00417 { 00418 struct addrmap_fixed *fixed = (struct addrmap_fixed *) closure; 00419 struct addrmap_transition *t = &fixed->transitions[fixed->num_transitions]; 00420 00421 t->addr = addrmap_node_key (n); 00422 t->value = addrmap_node_value (n); 00423 fixed->num_transitions++; 00424 00425 return 0; 00426 } 00427 00428 00429 static struct addrmap * 00430 addrmap_mutable_create_fixed (struct addrmap *this, struct obstack *obstack) 00431 { 00432 struct addrmap_mutable *mutable = (struct addrmap_mutable *) this; 00433 struct addrmap_fixed *fixed; 00434 size_t num_transitions; 00435 00436 /* Count the number of transitions in the tree. */ 00437 num_transitions = 0; 00438 splay_tree_foreach (mutable->tree, splay_foreach_count, &num_transitions); 00439 00440 /* Include an extra entry for the transition at zero (which fixed 00441 maps have, but mutable maps do not.) */ 00442 num_transitions++; 00443 00444 fixed = obstack_alloc (obstack, 00445 (sizeof (*fixed) 00446 + (num_transitions 00447 * sizeof (fixed->transitions[0])))); 00448 fixed->addrmap.funcs = &addrmap_fixed_funcs; 00449 fixed->num_transitions = 1; 00450 fixed->transitions[0].addr = 0; 00451 fixed->transitions[0].value = NULL; 00452 00453 /* Copy all entries from the splay tree to the array, in order 00454 of increasing address. */ 00455 splay_tree_foreach (mutable->tree, splay_foreach_copy, fixed); 00456 00457 /* We should have filled the array. */ 00458 gdb_assert (fixed->num_transitions == num_transitions); 00459 00460 return (struct addrmap *) fixed; 00461 } 00462 00463 00464 static void 00465 addrmap_mutable_relocate (struct addrmap *this, CORE_ADDR offset) 00466 { 00467 /* Not needed yet. */ 00468 internal_error (__FILE__, __LINE__, 00469 _("addrmap_relocate is not implemented yet " 00470 "for mutable addrmaps")); 00471 } 00472 00473 00474 /* Struct to map addrmap's foreach function to splay_tree's version. */ 00475 struct mutable_foreach_data 00476 { 00477 addrmap_foreach_fn fn; 00478 void *data; 00479 }; 00480 00481 00482 /* This is a splay_tree_foreach_fn. */ 00483 00484 static int 00485 addrmap_mutable_foreach_worker (splay_tree_node node, void *data) 00486 { 00487 struct mutable_foreach_data *foreach_data = data; 00488 00489 return foreach_data->fn (foreach_data->data, 00490 addrmap_node_key (node), 00491 addrmap_node_value (node)); 00492 } 00493 00494 00495 static int 00496 addrmap_mutable_foreach (struct addrmap *this, addrmap_foreach_fn fn, 00497 void *data) 00498 { 00499 struct addrmap_mutable *mutable = (struct addrmap_mutable *) this; 00500 struct mutable_foreach_data foreach_data; 00501 00502 foreach_data.fn = fn; 00503 foreach_data.data = data; 00504 return splay_tree_foreach (mutable->tree, addrmap_mutable_foreach_worker, 00505 &foreach_data); 00506 } 00507 00508 00509 static const struct addrmap_funcs addrmap_mutable_funcs = 00510 { 00511 addrmap_mutable_set_empty, 00512 addrmap_mutable_find, 00513 addrmap_mutable_create_fixed, 00514 addrmap_mutable_relocate, 00515 addrmap_mutable_foreach 00516 }; 00517 00518 00519 static void * 00520 splay_obstack_alloc (int size, void *closure) 00521 { 00522 struct addrmap_mutable *map = closure; 00523 splay_tree_node n; 00524 00525 /* We should only be asked to allocate nodes and larger things. 00526 (If, at some point in the future, this is no longer true, we can 00527 just round up the size to sizeof (*n).) */ 00528 gdb_assert (size >= sizeof (*n)); 00529 00530 if (map->free_nodes) 00531 { 00532 n = map->free_nodes; 00533 map->free_nodes = n->right; 00534 return n; 00535 } 00536 else 00537 return obstack_alloc (map->obstack, size); 00538 } 00539 00540 00541 static void 00542 splay_obstack_free (void *obj, void *closure) 00543 { 00544 struct addrmap_mutable *map = closure; 00545 splay_tree_node n = obj; 00546 00547 /* We've asserted in the allocation function that we only allocate 00548 nodes or larger things, so it should be safe to put whatever 00549 we get passed back on the free list. */ 00550 n->right = map->free_nodes; 00551 map->free_nodes = n; 00552 } 00553 00554 00555 /* Compare keys as CORE_ADDR * values. */ 00556 static int 00557 splay_compare_CORE_ADDR_ptr (splay_tree_key ak, splay_tree_key bk) 00558 { 00559 CORE_ADDR a = * (CORE_ADDR *) ak; 00560 CORE_ADDR b = * (CORE_ADDR *) bk; 00561 00562 /* We can't just return a-b here, because of over/underflow. */ 00563 if (a < b) 00564 return -1; 00565 else if (a == b) 00566 return 0; 00567 else 00568 return 1; 00569 } 00570 00571 00572 struct addrmap * 00573 addrmap_create_mutable (struct obstack *obstack) 00574 { 00575 struct addrmap_mutable *map = obstack_alloc (obstack, sizeof (*map)); 00576 00577 map->addrmap.funcs = &addrmap_mutable_funcs; 00578 map->obstack = obstack; 00579 00580 /* splay_tree_new_with_allocator uses the provided allocation 00581 function to allocate the main splay_tree structure itself, so our 00582 free list has to be initialized before we create the tree. */ 00583 map->free_nodes = NULL; 00584 00585 map->tree = splay_tree_new_with_allocator (splay_compare_CORE_ADDR_ptr, 00586 NULL, /* no delete key */ 00587 NULL, /* no delete value */ 00588 splay_obstack_alloc, 00589 splay_obstack_free, 00590 map); 00591 00592 return (struct addrmap *) map; 00593 } 00594 00595 00596 00597 /* Initialization. */ 00598 00599 /* Provide a prototype to silence -Wmissing-prototypes. */ 00600 extern initialize_file_ftype _initialize_addrmap; 00601 00602 void 00603 _initialize_addrmap (void) 00604 { 00605 /* Make sure splay trees can actually hold the values we want to 00606 store in them. */ 00607 gdb_assert (sizeof (splay_tree_key) >= sizeof (CORE_ADDR *)); 00608 gdb_assert (sizeof (splay_tree_value) >= sizeof (void *)); 00609 }