From: Simon Marchi Date: Tue, 3 Jan 2023 17:48:48 +0000 (-0500) Subject: gdb: move frame_info_ptr to frame.{c,h} X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=43e8c9ce20357a12dc5ccaf9ac84eea2cb6aa39b;p=binutils-gdb.git gdb: move frame_info_ptr to frame.{c,h} A patch later in this series will make frame_info_ptr access some fields internal to frame_info, which we don't want to expose outside of frame.c. Move the frame_info_ptr class to frame.h, and the definitions to frame.c. Remove frame-info.c and frame-info.h. Change-Id: Ic5949759e6262ea0da6123858702d48fe5673fea Reviewed-By: Bruno Larsen --- diff --git a/gdb/Makefile.in b/gdb/Makefile.in index b22a6c624a6..cce85b87436 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1087,7 +1087,6 @@ COMMON_SFILES = \ findvar.c \ frame.c \ frame-base.c \ - frame-info.c \ frame-unwind.c \ gcore.c \ gdb-demangle.c \ diff --git a/gdb/c-lang.h b/gdb/c-lang.h index 8a82606b6d0..1d6b90cca19 100644 --- a/gdb/c-lang.h +++ b/gdb/c-lang.h @@ -25,6 +25,7 @@ struct ui_file; struct language_arch_info; struct type_print_options; struct parser_state; +struct compile_instance; #include "compile/compile.h" #include "value.h" diff --git a/gdb/dwarf2/call-site.h b/gdb/dwarf2/call-site.h index f5bee967594..c8a1e8b2971 100644 --- a/gdb/dwarf2/call-site.h +++ b/gdb/dwarf2/call-site.h @@ -23,8 +23,8 @@ #define CALL_SITE_H #include "dwarf2/types.h" +#include "../frame.h" #include "gdbsupport/function-view.h" -#include "frame-info.h" struct dwarf2_locexpr_baton; struct dwarf2_per_cu_data; diff --git a/gdb/frame-info.c b/gdb/frame-info.c deleted file mode 100644 index 99d92cd555d..00000000000 --- a/gdb/frame-info.c +++ /dev/null @@ -1,65 +0,0 @@ -/* Frame info pointer - - Copyright (C) 2022-2023 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - 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 . */ - -#include "defs.h" - -#include "frame-info.h" -#include "frame.h" - -/* See frame-info-ptr.h. */ - -intrusive_list frame_info_ptr::frame_list; - -/* See frame-info-ptr.h. */ - -void -frame_info_ptr::prepare_reinflate () -{ - m_cached_level = frame_relative_level (*this); - - if (m_cached_level != 0) - m_cached_id = get_frame_id (*this); -} - -/* See frame-info-ptr.h. */ - -void -frame_info_ptr::reinflate () -{ - /* Ensure we have a valid frame level (sentinel frame or above), indicating - prepare_reinflate was called. */ - gdb_assert (m_cached_level >= -1); - - if (m_ptr != nullptr) - { - /* The frame_info wasn't invalidated, no need to reinflate. */ - return; - } - - /* Frame #0 needs special handling, see comment in select_frame. */ - if (m_cached_level == 0) - m_ptr = get_current_frame ().get (); - else - { - gdb_assert (frame_id_p (m_cached_id)); - m_ptr = frame_find_by_id (m_cached_id).get (); - } - - gdb_assert (m_ptr != nullptr); -} diff --git a/gdb/frame-info.h b/gdb/frame-info.h deleted file mode 100644 index d0fe9d6a85e..00000000000 --- a/gdb/frame-info.h +++ /dev/null @@ -1,211 +0,0 @@ -/* Frame info pointer - - Copyright (C) 2022-2023 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - 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 . */ - -#ifndef GDB_FRAME_INFO_H -#define GDB_FRAME_INFO_H - -#include "gdbsupport/intrusive_list.h" -#include "frame-id.h" - -struct frame_info; - -/* A wrapper for "frame_info *". frame_info objects are invalidated - whenever reinit_frame_cache is called. This class arranges to - invalidate the pointer when appropriate. This is done to help - detect a GDB bug that was relatively common. - - A small amount of code must still operate on raw pointers, so a - "get" method is provided. However, you should normally not use - this in new code. */ - -class frame_info_ptr : public intrusive_list_node -{ -public: - /* Create a frame_info_ptr from a raw pointer. */ - explicit frame_info_ptr (struct frame_info *ptr) - : m_ptr (ptr) - { - frame_list.push_back (*this); - } - - /* Create a null frame_info_ptr. */ - frame_info_ptr () - { - frame_list.push_back (*this); - } - - frame_info_ptr (std::nullptr_t) - { - frame_list.push_back (*this); - } - - frame_info_ptr (const frame_info_ptr &other) - : m_ptr (other.m_ptr), - m_cached_id (other.m_cached_id), - m_cached_level (other.m_cached_level) - { - frame_list.push_back (*this); - } - - frame_info_ptr (frame_info_ptr &&other) - : m_ptr (other.m_ptr), - m_cached_id (other.m_cached_id), - m_cached_level (other.m_cached_level) - { - other.m_ptr = nullptr; - other.m_cached_id = null_frame_id; - other.m_cached_level = invalid_level; - frame_list.push_back (*this); - } - - ~frame_info_ptr () - { - /* If this node has static storage, it may be deleted after - frame_list. Attempting to erase ourselves would then trigger - internal errors, so make sure we are still linked first. */ - if (is_linked ()) - frame_list.erase (frame_list.iterator_to (*this)); - } - - frame_info_ptr &operator= (const frame_info_ptr &other) - { - m_ptr = other.m_ptr; - m_cached_id = other.m_cached_id; - m_cached_level = other.m_cached_level; - return *this; - } - - frame_info_ptr &operator= (std::nullptr_t) - { - m_ptr = nullptr; - m_cached_id = null_frame_id; - m_cached_level = invalid_level; - return *this; - } - - frame_info_ptr &operator= (frame_info_ptr &&other) - { - m_ptr = other.m_ptr; - m_cached_id = other.m_cached_id; - m_cached_level = other.m_cached_level; - other.m_ptr = nullptr; - other.m_cached_id = null_frame_id; - other.m_cached_level = invalid_level; - return *this; - } - - frame_info *operator-> () const - { - return m_ptr; - } - - /* Fetch the underlying pointer. Note that new code should - generally not use this -- avoid it if at all possible. */ - frame_info *get () const - { - return m_ptr; - } - - /* This exists for compatibility with pre-existing code that checked - a "frame_info *" using "!". */ - bool operator! () const - { - return m_ptr == nullptr; - } - - /* This exists for compatibility with pre-existing code that checked - a "frame_info *" like "if (ptr)". */ - explicit operator bool () const - { - return m_ptr != nullptr; - } - - /* Invalidate this pointer. */ - void invalidate () - { - m_ptr = nullptr; - } - - /* Cache the frame_id that the pointer will use to reinflate. */ - void prepare_reinflate (); - - /* Use the cached frame_id to reinflate the pointer. */ - void reinflate (); - -private: - /* We sometimes need to construct frame_info_ptr objects around the - sentinel_frame, which has level -1. Therefore, make the invalid frame - level value -2. */ - static constexpr int invalid_level = -2; - - /* The underlying pointer. */ - frame_info *m_ptr = nullptr; - - /* The frame_id of the underlying pointer. */ - frame_id m_cached_id = null_frame_id; - - /* The frame level of the underlying pointer. */ - int m_cached_level = invalid_level; - - /* All frame_info_ptr objects are kept on an intrusive list. - This keeps their construction and destruction costs - reasonably small. */ - static intrusive_list frame_list; - - /* A friend so it can invalidate the pointers. */ - friend void reinit_frame_cache (); -}; - -static inline bool -operator== (const frame_info *self, const frame_info_ptr &other) -{ - return self == other.get (); -} - -static inline bool -operator== (const frame_info_ptr &self, const frame_info_ptr &other) -{ - return self.get () == other.get (); -} - -static inline bool -operator== (const frame_info_ptr &self, const frame_info *other) -{ - return self.get () == other; -} - -static inline bool -operator!= (const frame_info *self, const frame_info_ptr &other) -{ - return self != other.get (); -} - -static inline bool -operator!= (const frame_info_ptr &self, const frame_info_ptr &other) -{ - return self.get () != other.get (); -} - -static inline bool -operator!= (const frame_info_ptr &self, const frame_info *other) -{ - return self.get () != other; -} - -#endif /* GDB_FRAME_INFO_H */ diff --git a/gdb/frame.c b/gdb/frame.c index 2f9622ad2b2..b5f48399703 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -19,7 +19,6 @@ #include "defs.h" #include "frame.h" -#include "frame-info.h" #include "target.h" #include "value.h" #include "inferior.h" /* for inferior_ptid */ @@ -3161,6 +3160,48 @@ maintenance_print_frame_id (const char *args, int from_tty) get_frame_id (frame).to_string ().c_str ()); } +/* See frame-info-ptr.h. */ + +intrusive_list frame_info_ptr::frame_list; + +/* See frame-info-ptr.h. */ + +void +frame_info_ptr::prepare_reinflate () +{ + m_cached_level = frame_relative_level (*this); + + if (m_cached_level != 0) + m_cached_id = get_frame_id (*this); +} + +/* See frame-info-ptr.h. */ + +void +frame_info_ptr::reinflate () +{ + /* Ensure we have a valid frame level (sentinel frame or above), indicating + prepare_reinflate was called. */ + gdb_assert (m_cached_level >= -1); + + if (m_ptr != nullptr) + { + /* The frame_info wasn't invalidated, no need to reinflate. */ + return; + } + + /* Frame #0 needs special handling, see comment in select_frame. */ + if (m_cached_level == 0) + m_ptr = get_current_frame ().get (); + else + { + gdb_assert (frame_id_p (m_cached_id)); + m_ptr = frame_find_by_id (m_cached_id).get (); + } + + gdb_assert (m_ptr != nullptr); +} + void _initialize_frame (); void _initialize_frame () diff --git a/gdb/frame.h b/gdb/frame.h index 2c2e320bf7d..70ad606c134 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -20,8 +20,6 @@ #if !defined (FRAME_H) #define FRAME_H 1 -#include "frame-info.h" - /* The following is the intended naming schema for frame functions. It isn't 100% consistent, but it is approaching that. Frame naming schema: @@ -72,7 +70,9 @@ */ #include "cli/cli-option.h" +#include "frame-id.h" #include "gdbsupport/common-debug.h" +#include "gdbsupport/intrusive_list.h" struct symtab_and_line; struct frame_unwind; @@ -85,7 +85,6 @@ struct frame_print_options; /* The frame object. */ -class frame_info_ptr; /* Save and restore the currently selected frame. */ @@ -194,6 +193,189 @@ enum frame_type SENTINEL_FRAME }; +/* A wrapper for "frame_info *". frame_info objects are invalidated + whenever reinit_frame_cache is called. This class arranges to + invalidate the pointer when appropriate. This is done to help + detect a GDB bug that was relatively common. + + A small amount of code must still operate on raw pointers, so a + "get" method is provided. However, you should normally not use + this in new code. */ + +class frame_info_ptr : public intrusive_list_node +{ +public: + /* Create a frame_info_ptr from a raw pointer. */ + explicit frame_info_ptr (struct frame_info *ptr) + : m_ptr (ptr) + { + frame_list.push_back (*this); + } + + /* Create a null frame_info_ptr. */ + frame_info_ptr () + { + frame_list.push_back (*this); + } + + frame_info_ptr (std::nullptr_t) + { + frame_list.push_back (*this); + } + + frame_info_ptr (const frame_info_ptr &other) + : m_ptr (other.m_ptr), + m_cached_id (other.m_cached_id), + m_cached_level (other.m_cached_level) + { + frame_list.push_back (*this); + } + + frame_info_ptr (frame_info_ptr &&other) + : m_ptr (other.m_ptr), + m_cached_id (other.m_cached_id), + m_cached_level (other.m_cached_level) + { + other.m_ptr = nullptr; + other.m_cached_id = null_frame_id; + other.m_cached_level = invalid_level; + frame_list.push_back (*this); + } + + ~frame_info_ptr () + { + /* If this node has static storage, it may be deleted after + frame_list. Attempting to erase ourselves would then trigger + internal errors, so make sure we are still linked first. */ + if (is_linked ()) + frame_list.erase (frame_list.iterator_to (*this)); + } + + frame_info_ptr &operator= (const frame_info_ptr &other) + { + m_ptr = other.m_ptr; + m_cached_id = other.m_cached_id; + m_cached_level = other.m_cached_level; + return *this; + } + + frame_info_ptr &operator= (std::nullptr_t) + { + m_ptr = nullptr; + m_cached_id = null_frame_id; + m_cached_level = invalid_level; + return *this; + } + + frame_info_ptr &operator= (frame_info_ptr &&other) + { + m_ptr = other.m_ptr; + m_cached_id = other.m_cached_id; + m_cached_level = other.m_cached_level; + other.m_ptr = nullptr; + other.m_cached_id = null_frame_id; + other.m_cached_level = invalid_level; + return *this; + } + + frame_info *operator-> () const + { + return m_ptr; + } + + /* Fetch the underlying pointer. Note that new code should + generally not use this -- avoid it if at all possible. */ + frame_info *get () const + { + return m_ptr; + } + + /* This exists for compatibility with pre-existing code that checked + a "frame_info *" using "!". */ + bool operator! () const + { + return m_ptr == nullptr; + } + + /* This exists for compatibility with pre-existing code that checked + a "frame_info *" like "if (ptr)". */ + explicit operator bool () const + { + return m_ptr != nullptr; + } + + /* Invalidate this pointer. */ + void invalidate () + { + m_ptr = nullptr; + } + + /* Cache the frame_id that the pointer will use to reinflate. */ + void prepare_reinflate (); + + /* Use the cached frame_id to reinflate the pointer. */ + void reinflate (); + +private: + /* We sometimes need to construct frame_info_ptr objects around the + sentinel_frame, which has level -1. Therefore, make the invalid frame + level value -2. */ + static constexpr int invalid_level = -2; + + /* The underlying pointer. */ + frame_info *m_ptr = nullptr; + + /* The frame_id of the underlying pointer. */ + frame_id m_cached_id = null_frame_id; + + /* The frame level of the underlying pointer. */ + int m_cached_level = invalid_level; + + /* All frame_info_ptr objects are kept on an intrusive list. + This keeps their construction and destruction costs + reasonably small. */ + static intrusive_list frame_list; + + /* A friend so it can invalidate the pointers. */ + friend void reinit_frame_cache (); +}; + +static inline bool +operator== (const frame_info *self, const frame_info_ptr &other) +{ + return self == other.get (); +} + +static inline bool +operator== (const frame_info_ptr &self, const frame_info_ptr &other) +{ + return self.get () == other.get (); +} + +static inline bool +operator== (const frame_info_ptr &self, const frame_info *other) +{ + return self.get () == other; +} + +static inline bool +operator!= (const frame_info *self, const frame_info_ptr &other) +{ + return self != other.get (); +} + +static inline bool +operator!= (const frame_info_ptr &self, const frame_info_ptr &other) +{ + return self.get () != other.get (); +} + +static inline bool +operator!= (const frame_info_ptr &self, const frame_info *other) +{ + return self.get () != other; +} + /* For every stopped thread, GDB tracks two frames: current and selected. Current frame is the inner most frame of the selected thread. Selected frame is the one being examined by the GDB diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 6b643fcdaee..18ea1bca19c 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -56,7 +56,6 @@ #include "dwarf2.h" #include "gdbsupport/gdb_obstack.h" #include "gmp-utils.h" -#include "frame-info.h" /* Forward declarations for prototypes. */ struct field; @@ -1734,7 +1733,6 @@ struct func_type struct type *self_type; }; - /* The type-specific info for TYPE_CODE_FIXED_POINT types. */ struct fixed_point_type_info diff --git a/gdb/symtab.h b/gdb/symtab.h index ae3a81991df..3ba40bd9af5 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -37,6 +37,7 @@ #include "completer.h" #include "gdb-demangle.h" #include "split-name.h" +#include "frame.h" /* Opaque declarations. */ struct ui_file;