GDB (API)
/home/stan/gdb/src/gdb/addrmap.c
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines