[2/4] Add function for partitioning/splitting a section table

Message ID 20200305004243.334607-3-kevinb@redhat.com
State New
Headers show
Series
  • Fix BZ 25631 - core file memory access problem
Related show

Commit Message

Kevin Buettner March 5, 2020, 12:42 a.m.
gdb/ChangeLog:
	* exec.h, exec.c (split_section_table): New function.

Change-Id: I8909174aed892727bdd6d704cfe43763ee8969c3
---
 gdb/exec.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/exec.h | 13 +++++++++++++
 2 files changed, 68 insertions(+)

-- 
2.24.1

Comments

Jose E. Marchesi via Gdb-patches March 25, 2020, 5:25 p.m. | #1
Hi, Kevin,

Thank you for looking into this bug, which I have some familiarity with.
Like you, the BFD hack made me a little nervous. I am relieved that I
was apparently barking up the right proverbial tree.

Comments/(rhetorical) questions inline.

On 3/4/20 4:42 PM, Kevin Buettner wrote:

> gdb/ChangeLog:

>	* exec.h, exec.c (split_section_table): New function.


Mention "PR corefiles/25631"?

>  gdb/exec.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++

>  gdb/exec.h | 13 +++++++++++++

>  2 files changed, 68 insertions(+)

> 

> diff --git a/gdb/exec.c b/gdb/exec.c

> index 68bca1be17..e8cd471f5f 100644

> --- a/gdb/exec.c

> +++ b/gdb/exec.c

> @@ -604,6 +604,61 @@ resize_section_table (struct target_section_table *table, int adjustment)

>    return old_count;

>  }

>  

> +/* See exec.h.  */

> +

> +void

> +split_section_table (struct target_section_table *orig,

> +		     struct target_section_table *splits,

> +		     bool (*criterion) (struct target_section *))

> +{

> +  int count = 0;

> +

> +  for (struct target_section *sect = orig->sections;

> +       sect < orig->sections_end;

> +       sect++)

> +    {

> +      if (criterion (sect))

> +	count++;

> +    }

> +


I admit, I am hesitant about looping over this `criterion' evaluation twice
(once here, once below), especially given BFD's propensity to turn everything into
a section, but I realize you're working with some pre-existing APIs that would
need rewriting. [Rewriting, e.g., build_section_table doesn't seem so important
in the grand scheme of things.] 

Still, I wonder if the double-looping might be avoidable using vectors
(partially at least) or XRESIZEVEC?

> +  /* Handle the case of an empty SPLITS table.  */

> +  if (count == 0)

> +    {

> +      splits->sections = nullptr;

> +      splits->sections_end = nullptr;

> +      return;

> +    }

> +

> +  /* Handle case of an empty ORIG table.  */

> +  if (count == orig->sections_end - orig->sections)

> +    {

> +      splits = orig;

         ^^^^^^^^^^^^^^
Typo?

> +      orig->sections = nullptr;

> +      orig->sections_end = nullptr;

> +      return;

> +    }

> +

> +  /* Okay, we actually have something to do.  Allocate a new table for

> +     SPLITS.  We'll resize ORIG after copying.  */

> +

> +  splits->sections = XNEWVEC (struct target_section, count);

> +  splits->sections_end = splits->sections + count;

> +

> +  for (struct target_section *sect = orig->sections,

> +                             *osect = sect,

> +                             *ssect = splits->sections;

> +       sect < orig->sections_end;

> +       sect++)

> +    {

> +      if (criterion (sect))

> +	*ssect++ = *sect;

> +      else

> +        *osect++ = *sect;

> +    }

> +

> +  resize_section_table (orig, -count);

> +}

> +

>  /* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.

>     Returns 0 if OK, 1 on error.  */


Rambling notwithstanding, LGTM.

Thanks again for picking this up.

Keith

Patch

diff --git a/gdb/exec.c b/gdb/exec.c
index 68bca1be17..e8cd471f5f 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -604,6 +604,61 @@  resize_section_table (struct target_section_table *table, int adjustment)
   return old_count;
 }
 
+/* See exec.h.  */
+
+void
+split_section_table (struct target_section_table *orig,
+		     struct target_section_table *splits,
+		     bool (*criterion) (struct target_section *))
+{
+  int count = 0;
+
+  for (struct target_section *sect = orig->sections;
+       sect < orig->sections_end;
+       sect++)
+    {
+      if (criterion (sect))
+	count++;
+    }
+
+  /* Handle the case of an empty SPLITS table.  */
+  if (count == 0)
+    {
+      splits->sections = nullptr;
+      splits->sections_end = nullptr;
+      return;
+    }
+
+  /* Handle case of an empty ORIG table.  */
+  if (count == orig->sections_end - orig->sections)
+    {
+      splits = orig;
+      orig->sections = nullptr;
+      orig->sections_end = nullptr;
+      return;
+    }
+
+  /* Okay, we actually have something to do.  Allocate a new table for
+     SPLITS.  We'll resize ORIG after copying.  */
+
+  splits->sections = XNEWVEC (struct target_section, count);
+  splits->sections_end = splits->sections + count;
+
+  for (struct target_section *sect = orig->sections,
+                             *osect = sect,
+                             *ssect = splits->sections;
+       sect < orig->sections_end;
+       sect++)
+    {
+      if (criterion (sect))
+	*ssect++ = *sect;
+      else
+        *osect++ = *sect;
+    }
+
+  resize_section_table (orig, -count);
+}
+
 /* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.
    Returns 0 if OK, 1 on error.  */
 
diff --git a/gdb/exec.h b/gdb/exec.h
index 54e6ff4d9b..fc45e11898 100644
--- a/gdb/exec.h
+++ b/gdb/exec.h
@@ -44,6 +44,19 @@  extern int build_section_table (struct bfd *, struct target_section **,
 
 extern void clear_section_table (struct target_section_table *table);
 
+/* Split a target section table ORIG into two parts.  Sections meeting
+   CRITERION will be placed into SPLITS.  The original table ORIG will
+   be adjusted and resized as necessary, removing those sections which
+   were placed into SPLITS.  If no sections in ORIG satisfy CRITERION,
+   sections and sections_end in SPLITS will be set to nullptr,
+   representing an empty table.  Likewise, if all sections in ORIG
+   satisfy CRITERION, ORIG will be set to an empty table and SPLITS
+   end up with all of the sections originally in ORIG.  */
+
+extern void split_section_table (struct target_section_table *orig,
+				 struct target_section_table *splits,
+				 bool (*criterion) (struct target_section *));
+
 /* The current inferior is a child vforked and its program space is
    shared with its parent.  This pushes the exec target on the
    current/child inferior's target stack if there are sections in the