diff options
Diffstat (limited to 'devel/gdb/files/commit-3c3ae77e68')
-rw-r--r-- | devel/gdb/files/commit-3c3ae77e68 | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/devel/gdb/files/commit-3c3ae77e68 b/devel/gdb/files/commit-3c3ae77e68 new file mode 100644 index 000000000000..bd232d7031a6 --- /dev/null +++ b/devel/gdb/files/commit-3c3ae77e68 @@ -0,0 +1,156 @@ +commit 3c3ae77e68a9032ef9f174bf6b1cc992b6a4cb35 +Author: Pedro Alves <palves@redhat.com> +Date: Thu May 4 15:14:37 2017 +0100 + + Fix get_core_register_section leak, introduce thread_section_name + + This plugs a leak introduced in the previous change to + get_core_register_section, which removed an xfree call that is + actually necessary because the 'section_name' local is static. + + From [1] it looks like the reason the variable was made static to + begin with, was just "laziness" to avoid having to think about freeing + it on every function return path: + + https://sourceware.org/ml/gdb-patches/2005-03/msg00237.html + + The easiest to fix that nowadays is to use a std::string. + + I don't see a need to xstrdup the section name in the single-threaded + case though, and also there's more than one place that computes a + multi-threaded section name in the same way. So put the section name + computation in a wrapper class with state. + + gdb/ChangeLog: + 2017-05-04 Pedro Alves <palves@redhat.com> + + * corelow.c (thread_section_name): New class. + (get_core_register_section, get_core_siginfo): Use it. + +diff --git gdb/corelow.c gdb/corelow.c +index 2266f2467a..0aff02d4db 100644 +--- gdb/corelow.c ++++ gdb/corelow.c +@@ -485,6 +485,51 @@ core_detach (struct target_ops *ops, const char *args, int from_tty) + printf_filtered (_("No core file now.\n")); + } + ++/* Build either a single-thread or multi-threaded section name for ++ PTID. ++ ++ If ptid's lwp member is zero, we want to do the single-threaded ++ thing: look for a section named NAME (as passed to the ++ constructor). If ptid's lwp member is non-zero, we'll want do the ++ multi-threaded thing: look for a section named "NAME/LWP", where ++ LWP is the shortest ASCII decimal representation of ptid's lwp ++ member. */ ++ ++class thread_section_name ++{ ++public: ++ /* NAME is the single-threaded section name. If PTID represents an ++ LWP, then the build section name is "NAME/LWP", otherwise it's ++ just "NAME" unmodified. */ ++ thread_section_name (const char *name, ptid_t ptid) ++ { ++ if (ptid.lwp_p ()) ++ { ++ m_storage = string_printf ("%s/%ld", name, ptid.lwp ()); ++ m_section_name = m_storage.c_str (); ++ } ++ else ++ m_section_name = name; ++ } ++ ++ /* Return the computed section name. The result is valid as long as ++ this thread_section_name object is live. */ ++ const char *c_str () const ++ { return m_section_name; } ++ ++ /* Disable copy. */ ++ thread_section_name (const thread_section_name &) = delete; ++ void operator= (const thread_section_name &) = delete; ++ ++private: ++ /* Either a pointer into M_STORAGE, or a pointer to the name passed ++ as parameter to the constructor. */ ++ const char *m_section_name; ++ /* If we need to build a new section name, this is where we store ++ it. */ ++ std::string m_storage; ++}; ++ + /* Try to retrieve registers from a section in core_bfd, and supply + them to core_vec->core_read_registers, as the register set numbered + WHICH. +@@ -511,21 +556,15 @@ get_core_register_section (struct regcache *regcache, + const char *human_name, + int required) + { +- static char *section_name; + struct bfd_section *section; + bfd_size_type size; + char *contents; + bool variable_size_section = (regset != NULL + && regset->flags & REGSET_VARIABLE_SIZE); +- ptid_t ptid = regcache_get_ptid (regcache); + +- if (ptid_get_lwp (ptid)) +- section_name = xstrprintf ("%s/%ld", name, +- ptid_get_lwp (ptid)); +- else +- section_name = xstrdup (name); ++ thread_section_name section_name (name, regcache->ptid ()); + +- section = bfd_get_section_by_name (core_bfd, section_name); ++ section = bfd_get_section_by_name (core_bfd, section_name.c_str ()); + if (! section) + { + if (required) +@@ -537,13 +576,14 @@ get_core_register_section (struct regcache *regcache, + size = bfd_section_size (core_bfd, section); + if (size < min_size) + { +- warning (_("Section `%s' in core file too small."), section_name); ++ warning (_("Section `%s' in core file too small."), ++ section_name.c_str ()); + return; + } + if (size != min_size && !variable_size_section) + { + warning (_("Unexpected size of section `%s' in core file."), +- section_name); ++ section_name.c_str ()); + } + + contents = (char *) alloca (size); +@@ -551,7 +591,7 @@ get_core_register_section (struct regcache *regcache, + (file_ptr) 0, size)) + { + warning (_("Couldn't read %s registers from `%s' section in core file."), +- human_name, name); ++ human_name, section_name.c_str ()); + return; + } + +@@ -681,18 +721,8 @@ add_to_spuid_list (bfd *abfd, asection *asect, void *list_p) + static LONGEST + get_core_siginfo (bfd *abfd, gdb_byte *readbuf, ULONGEST offset, ULONGEST len) + { +- asection *section; +- char *section_name; +- const char *name = ".note.linuxcore.siginfo"; +- +- if (ptid_get_lwp (inferior_ptid)) +- section_name = xstrprintf ("%s/%ld", name, +- ptid_get_lwp (inferior_ptid)); +- else +- section_name = xstrdup (name); +- +- section = bfd_get_section_by_name (abfd, section_name); +- xfree (section_name); ++ thread_section_name section_name (".note.linuxcore.siginfo", inferior_ptid); ++ asection *section = bfd_get_section_by_name (abfd, section_name.c_str ()); + if (section == NULL) + return -1; + |