[PATCH 4/5] gdb: move file note iteration to elfnote-file.h/c

Mihails Strasuns mihails.strasuns@intel.com
Sun Jan 3 13:02:59 GMT 2021


Moves existing NT_FILE iteration code from linux-tdep.c to a recently
introduced elfnote-file translation unit and updates linux-tdep.c to use
that instead.  Moved code is slightly changed to be more in sync with
file note builder - uses unpack_long and TYPE_LENGTH rather than
addr bits.

Alternative interface was considered to provide a C++ range/iterator
API, however, it was decided that a considerable additional boilerplate
in this case is not justified, as any kind of complex iteration
algorithms on top of file mappings seem very unlikely.

gdb/ChangeLog:
2020-12-28  Mihails Strasuns  <mihails.strasuns@intel.com>

	* elfnote-file.h, elfnote-file.c (iterate_file_mappings): New function.
	* linux-tdep.c (linux_read_core_file_mappings): Start using
	  elfnote-file.
---
 gdb/elfnote-file.c | 71 +++++++++++++++++++++++++++++++++++++++++++
 gdb/elfnote-file.h |  9 ++++++
 gdb/linux-tdep.c   | 75 +++++++---------------------------------------
 3 files changed, 91 insertions(+), 64 deletions(-)

diff --git a/gdb/elfnote-file.c b/gdb/elfnote-file.c
index 4e35aff7df..70dcfcaf23 100644
--- a/gdb/elfnote-file.c
+++ b/gdb/elfnote-file.c
@@ -83,3 +83,74 @@ file_mappings_builder::build ()
 
   return gdb::byte_vector ();
 }
+
+/* See elfnote-file.h.  */
+
+void iterate_file_mappings (gdb::byte_vector *section, type *long_type,
+			    gdb::function_view<void (int)> pre_cb,
+			    gdb::function_view<void (int, const file_mapping&)> cb)
+{
+  ULONGEST addr_size = TYPE_LENGTH (long_type);
+
+  if (section->size () < 2 * addr_size)
+    {
+      warning (_("malformed core note - too short for header"));
+      return;
+    }
+
+  gdb_byte *descdata = section->data ();
+  char *descend = (char *) descdata + section->size ();
+
+  if (descdata[section->size() - 1] != '\0')
+    {
+      warning (_("malformed note - does not end with \\0"));
+      return;
+    }
+
+  ULONGEST count = unpack_long (long_type, descdata);
+  descdata += addr_size;
+
+  ULONGEST page_size = unpack_long (long_type, descdata);
+  descdata += addr_size;
+
+  if (section->size () < 2 * addr_size + count * 3 * addr_size)
+    {
+      warning (_("malformed note - too short for supplied file count"));
+      return;
+    }
+
+  char *filenames = (char *) descdata + count * 3 * addr_size;
+
+  /* Make sure that the correct number of filenames exist.  Complain
+     if there aren't enough or are too many.  */
+  char *f = filenames;
+  for (int i = 0; i < count; i++)
+    {
+      if (f >= descend)
+	{
+	  warning (_("malformed note - filename area is too small"));
+	  return;
+	}
+      f += strnlen (f, descend - f) + 1;
+    }
+  /* Complain, but don't return early if the filename area is too big.  */
+  if (f != descend)
+    warning (_("malformed note - filename area is too big"));
+
+  pre_cb (count);
+
+  for (int i = 0; i < count; i++)
+    {
+      ULONGEST start = unpack_long (long_type, descdata);
+      descdata += addr_size;
+      ULONGEST end = unpack_long (long_type, descdata);
+      descdata += addr_size;
+      ULONGEST file_ofs
+	= unpack_long (long_type, descdata) * page_size;
+      descdata += addr_size;
+      char * filename = filenames;
+      filenames += strlen ((char *) filenames) + 1;
+
+      cb (i, {start, end-start, file_ofs, filename});
+    }
+}
\ No newline at end of file
diff --git a/gdb/elfnote-file.h b/gdb/elfnote-file.h
index 09a150d4d0..6d620da8ee 100644
--- a/gdb/elfnote-file.h
+++ b/gdb/elfnote-file.h
@@ -27,6 +27,7 @@
 #include "defs.h"
 #include "gdbtypes.h"
 #include "gdbsupport/byte-vector.h"
+#include "gdbsupport/function-view.h"
 
 /* Fields for an individual NT_FILE element.  */
 struct file_mapping
@@ -59,4 +60,12 @@ class file_mappings_builder
   /* Finalizes creation of the note data and releases the data buffer.  */
   gdb::byte_vector build ();
 };
+
+/* Decode NT_FILE contents from data and calls cb for each individual file
+   mapping decoded.  Input byte vector is supposed be created via
+   bfd_get_section_contents or similar.  Before the iteration pre_cb
+   is called once providing file mapping count as an argument.  */
+void iterate_file_mappings (gdb::byte_vector *section, type *long_type,
+			    gdb::function_view<void (int)> pre_cb,
+			    gdb::function_view<void (int, const file_mapping&)> cb);
 #endif
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 8250c53bea..28ae5ea43d 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -1088,16 +1088,10 @@ linux_read_core_file_mappings (struct gdbarch *gdbarch,
   if (section == nullptr)
     return;
 
-  unsigned int addr_size_bits = gdbarch_addr_bit (gdbarch);
-  unsigned int addr_size = addr_size_bits / 8;
+  struct type *long_type
+    = arch_integer_type (gdbarch, gdbarch_long_bit (gdbarch), 0, "long");
+  
   size_t note_size = bfd_section_size (section);
-
-  if (note_size < 2 * addr_size)
-    {
-      warning (_("malformed core note - too short for header"));
-      return;
-    }
-
   gdb::def_vector<gdb_byte> contents (note_size);
   if (!bfd_get_section_contents (core_bfd, section, contents.data (),
 				 0, note_size))
@@ -1106,61 +1100,14 @@ linux_read_core_file_mappings (struct gdbarch *gdbarch,
       return;
     }
 
-  gdb_byte *descdata = contents.data ();
-  char *descend = (char *) descdata + note_size;
-
-  if (descdata[note_size - 1] != '\0')
-    {
-      warning (_("malformed note - does not end with \\0"));
-      return;
-    }
-
-  ULONGEST count = bfd_get (addr_size_bits, core_bfd, descdata);
-  descdata += addr_size;
-
-  ULONGEST page_size = bfd_get (addr_size_bits, core_bfd, descdata);
-  descdata += addr_size;
-
-  if (note_size < 2 * addr_size + count * 3 * addr_size)
-    {
-      warning (_("malformed note - too short for supplied file count"));
-      return;
-    }
-
-  char *filenames = (char *) descdata + count * 3 * addr_size;
-
-  /* Make sure that the correct number of filenames exist.  Complain
-     if there aren't enough or are too many.  */
-  char *f = filenames;
-  for (int i = 0; i < count; i++)
-    {
-      if (f >= descend)
-	{
-	  warning (_("malformed note - filename area is too small"));
-	  return;
-	}
-      f += strnlen (f, descend - f) + 1;
-    }
-  /* Complain, but don't return early if the filename area is too big.  */
-  if (f != descend)
-    warning (_("malformed note - filename area is too big"));
-
-  pre_loop_cb (count);
-
-  for (int i = 0; i < count; i++)
-    {
-      ULONGEST start = bfd_get (addr_size_bits, core_bfd, descdata);
-      descdata += addr_size;
-      ULONGEST end = bfd_get (addr_size_bits, core_bfd, descdata);
-      descdata += addr_size;
-      ULONGEST file_ofs
-	= bfd_get (addr_size_bits, core_bfd, descdata) * page_size;
-      descdata += addr_size;
-      char * filename = filenames;
-      filenames += strlen ((char *) filenames) + 1;
-
-      loop_cb (i, start, end, file_ofs, filename);
-    }
+  iterate_file_mappings (&contents, long_type, pre_loop_cb,
+  			 [=] (int i, const file_mapping& fm)
+			   {
+			     // expand file_mapping struct to avoid gdbarch
+			     // dependency on elfnote-file.h
+			     loop_cb (i, fm.vaddr, fm.vaddr+fm.size, fm.offset,
+				      fm.filename);
+			   });
 }
 
 /* Implement "info proc mappings" for a corefile.  */
-- 
2.17.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Christin Eisenschmid, Gary Kershaw
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928



More information about the Gdb-patches mailing list