gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / prologue-value.h
index 54d12a663d8f0917f40c3a509260a6cf82878800..99feffe8e4b0637ccb63606836c8701be34a7824 100644 (file)
@@ -1,6 +1,5 @@
 /* Interface to prologue value handling for GDB.
-   Copyright 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
-   Free Software Foundation, Inc.
+   Copyright (C) 2003-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #ifndef PROLOGUE_VALUE_H
 #define PROLOGUE_VALUE_H
 
+/* What sort of value is this?  This determines the interpretation
+   of subsequent fields.  */
+enum prologue_value_kind
+{
+  /* We don't know anything about the value.  This is also used for
+     values we could have kept track of, when doing so would have
+     been too complex and we don't want to bother.  The bottom of
+     our lattice.  */
+  pvk_unknown,
+
+  /* A known constant.  K is its value.  */
+  pvk_constant,
+
+  /* The value that register REG originally had *UPON ENTRY TO THE
+     FUNCTION*, plus K.  If K is zero, this means, obviously, just
+     the value REG had upon entry to the function.  REG is a GDB
+     register number.  Before we start interpreting, we initialize
+     every register R to { pvk_register, R, 0 }.  */
+  pvk_register,
+};
+
 /* When we analyze a prologue, we're really doing 'abstract
    interpretation' or 'pseudo-evaluation': running the function's code
    in simulation, but using conservative approximations of the values
    understand and maintain.  In the approach used here:
 
    - It's easier to see that the analyzer is correct: you just see
-     whether the analyzer properly (albiet conservatively) simulates
+     whether the analyzer properly (albeit conservatively) simulates
      the effect of each instruction.
 
    - It's easier to extend the analyzer: you can add support for new
@@ -121,25 +141,7 @@ struct prologue_value {
 
   /* What sort of value is this?  This determines the interpretation
      of subsequent fields.  */
-  enum {
-
-    /* We don't know anything about the value.  This is also used for
-       values we could have kept track of, when doing so would have
-       been too complex and we don't want to bother.  The bottom of
-       our lattice.  */
-    pvk_unknown,
-
-    /* A known constant.  K is its value.  */
-    pvk_constant,
-
-    /* The value that register REG originally had *UPON ENTRY TO THE
-       FUNCTION*, plus K.  If K is zero, this means, obviously, just
-       the value REG had upon entry to the function.  REG is a GDB
-       register number.  Before we start interpreting, we initialize
-       every register R to { pvk_register, R, 0 }.  */
-    pvk_register,
-
-  } kind;
+  enum prologue_value_kind kind;
 
   /* The meanings of the following fields depend on 'kind'; see the
      comments for the specific 'kind' values.  */
@@ -219,83 +221,110 @@ enum pv_boolean pv_is_array_ref (pv_t addr, CORE_ADDR size,
                                  int *i);
 
 
-/* A 'struct pv_area' keeps track of values stored in a particular
-   region of memory.  */
-struct pv_area;
+/* A 'pv_area' keeps track of values stored in a particular region of
+   memory.  */
+class pv_area
+{
+public:
 
-/* Create a new area, tracking stores relative to the original value
-   of BASE_REG.  If BASE_REG is SP, then this effectively records the
-   contents of the stack frame: the original value of the SP is the
-   frame's CFA, or some constant offset from it.
+  /* Create a new area, tracking stores relative to the original value
+     of BASE_REG.  If BASE_REG is SP, then this effectively records the
+     contents of the stack frame: the original value of the SP is the
+     frame's CFA, or some constant offset from it.
 
-   Stores to constant addresses, unknown addresses, or to addresses
-   relative to registers other than BASE_REG will trash this area; see
-   pv_area_store_would_trash.
+     Stores to constant addresses, unknown addresses, or to addresses
+     relative to registers other than BASE_REG will trash this area; see
+     pv_area::store_would_trash.
 
-   To check whether a pointer refers to this area, only the low
-   ADDR_BIT bits will be compared.  */
-struct pv_area *make_pv_area (int base_reg, int addr_bit);
+     To check whether a pointer refers to this area, only the low
+     ADDR_BIT bits will be compared.  */
+  pv_area (int base_reg, int addr_bit);
 
-/* Free AREA.  */
-void free_pv_area (struct pv_area *area);
+  ~pv_area ();
 
+  DISABLE_COPY_AND_ASSIGN (pv_area);
 
-/* Register a cleanup to free AREA.  */
-struct cleanup *make_cleanup_free_pv_area (struct pv_area *area);
+  /* Store the SIZE-byte value VALUE at ADDR in AREA.
 
+     If ADDR is not relative to the same base register we used in
+     creating AREA, then we can't tell which values here the stored
+     value might overlap, and we'll have to mark everything as
+     unknown.  */
+  void store (pv_t addr,
+             CORE_ADDR size,
+             pv_t value);
 
-/* Store the SIZE-byte value VALUE at ADDR in AREA.
+  /* Return the SIZE-byte value at ADDR in AREA.  This may return
+     pv_unknown ().  */
+  pv_t fetch (pv_t addr, CORE_ADDR size);
 
-   If ADDR is not relative to the same base register we used in
-   creating AREA, then we can't tell which values here the stored
-   value might overlap, and we'll have to mark everything as
-   unknown.  */
-void pv_area_store (struct pv_area *area,
-                    pv_t addr,
-                    CORE_ADDR size,
-                    pv_t value);
+  /* Return true if storing to address ADDR in AREA would force us to
+     mark the contents of the entire area as unknown.  This could happen
+     if, say, ADDR is unknown, since we could be storing anywhere.  Or,
+     it could happen if ADDR is relative to a different register than
+     the other stores base register, since we don't know the relative
+     values of the two registers.
 
-/* Return the SIZE-byte value at ADDR in AREA.  This may return
-   pv_unknown ().  */
-pv_t pv_area_fetch (struct pv_area *area, pv_t addr, CORE_ADDR size);
+     If you've reached such a store, it may be better to simply stop the
+     prologue analysis, and return the information you've gathered,
+     instead of losing all that information, most of which is probably
+     okay.  */
+  bool store_would_trash (pv_t addr);
 
-/* Return true if storing to address ADDR in AREA would force us to
-   mark the contents of the entire area as unknown.  This could happen
-   if, say, ADDR is unknown, since we could be storing anywhere.  Or,
-   it could happen if ADDR is relative to a different register than
-   the other stores base register, since we don't know the relative
-   values of the two registers.
+  /* Search AREA for the original value of REGISTER.  If we can't find
+     it, return zero; if we can find it, return a non-zero value, and if
+     OFFSET_P is non-zero, set *OFFSET_P to the register's offset within
+     AREA.  GDBARCH is the architecture of which REGISTER is a member.
 
-   If you've reached such a store, it may be better to simply stop the
-   prologue analysis, and return the information you've gathered,
-   instead of losing all that information, most of which is probably
-   okay.  */
-int pv_area_store_would_trash (struct pv_area *area, pv_t addr);
+     In the worst case, this takes time proportional to the number of
+     items stored in AREA.  If you plan to gather a lot of information
+     about registers saved in AREA, consider calling pv_area::scan
+     instead, and collecting all your information in one pass.  */
+  bool find_reg (struct gdbarch *gdbarch, int reg, CORE_ADDR *offset_p);
 
 
-/* Search AREA for the original value of REGISTER.  If we can't find
-   it, return zero; if we can find it, return a non-zero value, and if
-   OFFSET_P is non-zero, set *OFFSET_P to the register's offset within
-   AREA.  GDBARCH is the architecture of which REGISTER is a member.
+  /* For every part of AREA whose value we know, apply FUNC to CLOSURE,
+     the value's address, its size, and the value itself.  */
+  void scan (void (*func) (void *closure,
+                          pv_t addr,
+                          CORE_ADDR size,
+                          pv_t value),
+            void *closure);
 
-   In the worst case, this takes time proportional to the number of
-   items stored in AREA.  If you plan to gather a lot of information
-   about registers saved in AREA, consider calling pv_area_scan
-   instead, and collecting all your information in one pass.  */
-int pv_area_find_reg (struct pv_area *area,
-                      struct gdbarch *gdbarch,
-                      int reg,
-                      CORE_ADDR *offset_p);
+private:
 
+  struct area_entry;
 
-/* For every part of AREA whose value we know, apply FUNC to CLOSURE,
-   the value's address, its size, and the value itself.  */
-void pv_area_scan (struct pv_area *area,
-                   void (*func) (void *closure,
-                                 pv_t addr,
-                                 CORE_ADDR size,
-                                 pv_t value),
-                   void *closure);
+  /* Delete all entries from AREA.  */
+  void clear_entries ();
 
+  /* Return a pointer to the first entry we hit in AREA starting at
+     OFFSET and going forward.
+
+     This may return zero, if AREA has no entries.
+
+     And since the entries are a ring, this may return an entry that
+     entirely precedes OFFSET.  This is the correct behavior: depending
+     on the sizes involved, we could still overlap such an area, with
+     wrap-around.  */
+  struct area_entry *find_entry (CORE_ADDR offset);
+
+  /* Return non-zero if the SIZE bytes at OFFSET would overlap ENTRY;
+     return zero otherwise.  AREA is the area to which ENTRY belongs.  */
+  int overlaps (struct area_entry *entry,
+               CORE_ADDR offset,
+               CORE_ADDR size);
+
+  /* This area's base register.  */
+  int m_base_reg;
+
+  /* The mask to apply to addresses, to make the wrap-around happen at
+     the right place.  */
+  CORE_ADDR m_addr_mask;
+
+  /* An element of the doubly-linked ring of entries, or zero if we
+     have none.  */
+  struct area_entry *m_entry;
+};
 
 #endif /* PROLOGUE_VALUE_H */
This page took 0.028717 seconds and 4 git commands to generate.