Home | History | Annotate | Line # | Download | only in dwarf2
      1 /* DIE indexing
      2 
      3    Copyright (C) 2024 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 #ifndef GDB_DWARF2_PARENT_MAP_H
     21 #define GDB_DWARF2_PARENT_MAP_H
     22 
     23 #include <algorithm>
     24 
     25 class cooked_index_entry;
     26 
     27 /* A class that handles mapping from a DIE range to a parent
     28    entry.
     29 
     30    The generated DWARF can sometimes have the declaration for a method
     31    in a class (or perhaps namespace) scope, with the definition
     32    appearing outside this scope... just one of the many bad things
     33    about DWARF.  In order to handle this situation, we defer certain
     34    entries until the end of scanning, at which point we'll know the
     35    containing context of all the DIEs that we might have scanned.  */
     36 class parent_map
     37 {
     38 public:
     39 
     40   parent_map () = default;
     41   ~parent_map () = default;
     42 
     43   /* Move only.  */
     44   DISABLE_COPY_AND_ASSIGN (parent_map);
     45   parent_map (parent_map &&) = default;
     46   parent_map &operator= (parent_map &&) = default;
     47 
     48   /* A reasonably opaque type that is used here to combine a section
     49      offset and the 'dwz' flag into a single value.  */
     50   enum addr_type : CORE_ADDR { };
     51 
     52   /* Turn a section offset into a value that can be used in a parent
     53      map.  */
     54   static addr_type form_addr (sect_offset offset, bool is_dwz)
     55   {
     56     CORE_ADDR value = to_underlying (offset);
     57     if (is_dwz)
     58       value |= ((CORE_ADDR) 1) << (8 * sizeof (CORE_ADDR) - 1);
     59     return addr_type (value);
     60   }
     61 
     62   /* Add a new entry to this map.  DIEs from START to END, inclusive,
     63      are mapped to PARENT.  */
     64   void add_entry (addr_type start, addr_type end,
     65 		  const cooked_index_entry *parent)
     66   {
     67     gdb_assert (parent != nullptr);
     68     m_map.set_empty (start, end, (void *) parent);
     69   }
     70 
     71   /* Look up an entry in this map.  */
     72   const cooked_index_entry *find (addr_type search) const
     73   {
     74     return static_cast<const cooked_index_entry *> (m_map.find (search));
     75   }
     76 
     77   /* Return a fixed addrmap that is equivalent to this map.  */
     78   addrmap_fixed *to_fixed (struct obstack *obstack) const
     79   {
     80     return new (obstack) addrmap_fixed (obstack, &m_map);
     81   }
     82 
     83 private:
     84 
     85   /* An addrmap that maps from section offsets to cooked_index_entry *.  */
     86   addrmap_mutable m_map;
     87 };
     88 
     89 /* Keep a collection of parent_map objects, and allow for lookups
     90    across all of them.  */
     91 class parent_map_map
     92 {
     93 public:
     94 
     95   parent_map_map () = default;
     96   ~parent_map_map () = default;
     97 
     98   DISABLE_COPY_AND_ASSIGN (parent_map_map);
     99 
    100   /* Add a parent_map to this map.  */
    101   void add_map (const parent_map &map)
    102   {
    103     m_maps.push_back (map.to_fixed (&m_storage));
    104   }
    105 
    106   /* Look up an entry in this map.  */
    107   const cooked_index_entry *find (parent_map::addr_type search) const
    108   {
    109     for (const auto &iter : m_maps)
    110       {
    111 	const cooked_index_entry *result
    112 	  = static_cast<const cooked_index_entry *> (iter->find (search));
    113 	if (result != nullptr)
    114 	  return result;
    115       }
    116     return nullptr;
    117   }
    118 
    119 private:
    120 
    121   /* Storage for the convert maps.  */
    122   auto_obstack m_storage;
    123 
    124   /* While conceptually this class is a combination of parent_maps, in
    125      practice it is just a number of fixed maps.  This is important
    126      because we want to allow concurrent lookups, but a mutable
    127      addrmap is based on a splay-tree, which is not thread-safe, even
    128      for nominally read-only lookups.  */
    129   std::vector<addrmap_fixed *> m_maps;
    130 };
    131 
    132 #endif /* GDB_DWARF2_PARENT_MAP_H */
    133