gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / prologue-value.h
index d8e72178f27f0f0bd5821fea1ab576906f358b1b..99feffe8e4b0637ccb63606836c8701be34a7824 100644 (file)
@@ -1,11 +1,11 @@
 /* Interface to prologue value handling for GDB.
-   Copyright 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2003-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    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, write to:
-
-        Free Software Foundation, Inc.
-        51 Franklin St - Fifth Floor
-        Boston, MA 02110-1301
-        USA */
+   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
@@ -125,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.  */
@@ -223,80 +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.  */
-struct pv_area *make_pv_area (int base_reg);
+     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.
 
-/* Free AREA.  */
-void free_pv_area (struct pv_area *area);
+     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);
 
+  ~pv_area ();
 
-/* Register a cleanup to free AREA.  */
-struct cleanup *make_cleanup_free_pv_area (struct pv_area *area);
+  DISABLE_COPY_AND_ASSIGN (pv_area);
 
+  /* Store the SIZE-byte value VALUE at ADDR in 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);
 
-   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 the SIZE-byte value at ADDR in AREA.  This may return
+     pv_unknown ().  */
+  pv_t fetch (pv_t addr, CORE_ADDR size);
 
-/* 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);
+  /* 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 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.
+     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);
 
-   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);
+  /* 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.
 
+     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.
 
-   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);
+  /* 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);
 
+private:
 
-/* 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);
+  struct area_entry;
 
+  /* 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.027682 seconds and 4 git commands to generate.