[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