aboutsummaryrefslogtreecommitdiff
path: root/gdbsupport
diff options
context:
space:
mode:
authorAndrew Burgess <aburgess@redhat.com>2025-01-28 10:08:28 +0000
committerAndrew Burgess <aburgess@redhat.com>2025-01-29 09:46:15 +0000
commit146d4e2acecc4c34b3c0742e55e33653614a5ca1 (patch)
tree86918ef4905536c7b32f63f38186484df099a864 /gdbsupport
parente5e7d55dcb225be1a488e01d43cbce5fdec83a0f (diff)
downloadgdb-146d4e2acecc4c34b3c0742e55e33653614a5ca1.zip
gdb-146d4e2acecc4c34b3c0742e55e33653614a5ca1.tar.gz
gdb-146d4e2acecc4c34b3c0742e55e33653614a5ca1.tar.bz2
gdbserver: introduce and use new gdb::argv_vec class
In gdbserver there are a couple of places where we perform manual memory management using a 'std::vector<char *>' with the vector owning the strings within it. We need to take care to call free_vector_argv() before leaving the scope to cleanup the strings within the vector. This commit introduces a new class gdb::argv_vec which wraps around a 'std::vector<char *>' and owns the strings within the vector, taking care to xfree() them when the gdb::argv_vec is destroyed. Right now I plan to use this class in gdbserver. But this class will also be used to address review feedback on this commit: https://inbox.sourceware.org/gdb-patches/72227f1c5a2e350ca70b2151d1b91306a0261bdc.1736860317.git.aburgess@redhat.com where I tried to introduce another 'std::vector<char *>' which owns the strings. That patch will be updated to use gdb::argv_vec instead. The obvious question is, instead of introducing this new class, could we change the APIs to avoid having a std::vector<char *> that owns the strings? Could we use 'std::vector<std::string>' or 'std::vector<gdb::unique_xmalloc_ptr<char>>' instead? The answer is yes we could. I originally posted this larger patch set: https://inbox.sourceware.org/gdb-patches/cover.1730731085.git.aburgess@redhat.com however, getting a 14 patch series reviewed is just not possible, so instead, I'm posting the patches one at a time. The earlier patch I mentioned is pulled from the larger series. The larger series already includes changes to gdbserver which removes the need for the 'std::vector<char *>', however, getting those changes in depends (I think) on the patch I mention above. Hence we have a bit of a circular dependency. My proposal is to merge this patch (adding gdb::argv_vec) and make use of it in gdbserver. Then I'll update the patch above to also use gdb::argv_vec, which will allow the above patch to get reviewed and merged. Then I'll post, and hopefully merge additional patches from my larger inferior argument series, which will remove the need for gdb::argv_vec from gdbserver. At this point, the only use of gdb::argv_vec will be in the above patch, where I think it will remain, as I don't think that location can avoid using 'std::vector<char *>'. Approved-By: Tom Tromey <tom@tromey.com>
Diffstat (limited to 'gdbsupport')
-rw-r--r--gdbsupport/gdb_argv_vec.h139
1 files changed, 139 insertions, 0 deletions
diff --git a/gdbsupport/gdb_argv_vec.h b/gdbsupport/gdb_argv_vec.h
new file mode 100644
index 0000000..1f3b6db
--- /dev/null
+++ b/gdbsupport/gdb_argv_vec.h
@@ -0,0 +1,139 @@
+/* Wrap std::vector<char *> that owns the 'char *' strings.
+
+ Copyright (C) 2025 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef GDBSUPPORT_GDB_ARGV_VEC_H
+#define GDBSUPPORT_GDB_ARGV_VEC_H
+
+#include "gdbsupport/common-utils.h"
+#include <vector>
+
+namespace gdb
+{
+
+/* A class that wraps around a vector of 'char *' strings. The class owns
+ the strings within the vector and will release them by calling xfree()
+ on each string when this classes destructor is called. */
+class argv_vec final
+{
+ /* Vector of strings. This class owns the strings within the vector.
+ This is at the start of the class so we can use decltype(). */
+ std::vector<char *> m_args;
+
+public:
+
+ using value_type = decltype (m_args)::value_type;
+ using iterator = decltype (m_args)::iterator;
+ using const_iterator = decltype (m_args)::const_iterator;
+ using reference = decltype (m_args)::reference;
+ using const_reference = decltype (m_args)::const_reference;
+
+ argv_vec ()
+ {
+ /* Nothing. */
+ }
+
+ /* Move the owned strings from OTHER. */
+ argv_vec (argv_vec &&other)
+ {
+ this->m_args = std::move (other.m_args);
+ }
+
+ /* Don't currently support copying the strings from OTHER. */
+ argv_vec (const argv_vec &other) = delete;
+
+ /* Move elements from OTHER. Free currently owned strings. */
+ argv_vec &operator= (argv_vec &&other)
+ {
+ free_vector_argv (m_args);
+ this->m_args = std::move (other.m_args);
+ return *this;
+ }
+
+ /* Don't currently support copying the strings from OTHER. */
+ argv_vec &operator= (const argv_vec &other) = delete;
+
+ /* Release the owned strings. */
+ ~argv_vec ()
+ {
+ free_vector_argv (m_args);
+ }
+
+ /* Append VALUE to the end of m_args. This class takes ownership of
+ VALUE, and will release VALUE by calling xfree() on it when this
+ object is destroyed. */
+ void push_back (const value_type &value)
+ {
+ m_args.push_back (value);
+ }
+
+ /* Append VALUE to the end of m_args. This class takes ownership of
+ VALUE, and will release VALUE by calling xfree() on it when this
+ object is destroyed. */
+ void push_back (value_type &&value)
+ {
+ m_args.push_back (value);
+ }
+
+ /* Non constant iterator to start of m_args. */
+ iterator begin ()
+ {
+ return m_args.begin ();
+ }
+
+ /* Non constant iterator to end of m_args. */
+ iterator end ()
+ {
+ return m_args.end ();
+ }
+
+ /* Constant iterator to start of m_args. */
+ const_iterator begin () const
+ {
+ return m_args.begin ();
+ }
+
+ /* Constant iterator to end of m_args. */
+ const_iterator end () const
+ {
+ return m_args.end ();
+ }
+
+ /* Return contiguous block of 'char *' pointers. Ideally this would be
+ const, but the execve interface to which this data is passed doesn't
+ accept 'const char **'. */
+ char **argv ()
+ {
+ return m_args.data ();
+ }
+
+ /* Return a constant reference to the underlying vector. */
+ const decltype (m_args) &get () const
+ {
+ return m_args;
+ }
+
+ /* Return true when m_args is empty. */
+ bool empty () const
+ {
+ return m_args.empty ();
+ }
+};
+} /* namespac gdb */
+
+#endif /* GDBSUPPORT_GDB_ARGV_VEC_H */