aboutsummaryrefslogtreecommitdiff
path: root/gdb/linux-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/linux-tdep.c')
-rw-r--r--gdb/linux-tdep.c73
1 files changed, 60 insertions, 13 deletions
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 5de985d..c1666d1 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -586,8 +586,8 @@ mapping_is_anonymous_p (const char *filename)
}
/* Return 0 if the memory mapping (which is related to FILTERFLAGS, V,
- MAYBE_PRIVATE_P, and MAPPING_ANONYMOUS_P) should not be dumped, or
- greater than 0 if it should.
+ MAYBE_PRIVATE_P, MAPPING_ANONYMOUS_P, ADDR and OFFSET) should not
+ be dumped, or greater than 0 if it should.
In a nutshell, this is the logic that we follow in order to decide
if a mapping should be dumped or not.
@@ -625,12 +625,17 @@ mapping_is_anonymous_p (const char *filename)
see 'p' in the permission flags, then we assume that the mapping
is private, even though the presence of the 's' flag there would
mean VM_MAYSHARE, which means the mapping could still be private.
- This should work OK enough, however. */
+ This should work OK enough, however.
+
+ - Even if, at the end, we decided that we should not dump the
+ mapping, we still have to check if it is something like an ELF
+ header (of a DSO or an executable, for example). If it is, and
+ if the user is interested in dump it, then we should dump it. */
static int
dump_mapping_p (filter_flags filterflags, const struct smaps_vmflags *v,
int maybe_private_p, int mapping_anon_p, int mapping_file_p,
- const char *filename)
+ const char *filename, ULONGEST addr, ULONGEST offset)
{
/* Initially, we trust in what we received from our caller. This
value may not be very precise (i.e., it was probably gathered
@@ -640,6 +645,7 @@ dump_mapping_p (filter_flags filterflags, const struct smaps_vmflags *v,
(assuming that the version of the Linux kernel being used
supports it, of course). */
int private_p = maybe_private_p;
+ int dump_p;
/* We always dump vDSO and vsyscall mappings, because it's likely that
there'll be no file to read the contents from at core load time.
@@ -680,13 +686,13 @@ dump_mapping_p (filter_flags filterflags, const struct smaps_vmflags *v,
/* This is a special situation. It can happen when we see a
mapping that is file-backed, but that contains anonymous
pages. */
- return ((filterflags & COREFILTER_ANON_PRIVATE) != 0
- || (filterflags & COREFILTER_MAPPED_PRIVATE) != 0);
+ dump_p = ((filterflags & COREFILTER_ANON_PRIVATE) != 0
+ || (filterflags & COREFILTER_MAPPED_PRIVATE) != 0);
}
else if (mapping_anon_p)
- return (filterflags & COREFILTER_ANON_PRIVATE) != 0;
+ dump_p = (filterflags & COREFILTER_ANON_PRIVATE) != 0;
else
- return (filterflags & COREFILTER_MAPPED_PRIVATE) != 0;
+ dump_p = (filterflags & COREFILTER_MAPPED_PRIVATE) != 0;
}
else
{
@@ -695,14 +701,55 @@ dump_mapping_p (filter_flags filterflags, const struct smaps_vmflags *v,
/* This is a special situation. It can happen when we see a
mapping that is file-backed, but that contains anonymous
pages. */
- return ((filterflags & COREFILTER_ANON_SHARED) != 0
- || (filterflags & COREFILTER_MAPPED_SHARED) != 0);
+ dump_p = ((filterflags & COREFILTER_ANON_SHARED) != 0
+ || (filterflags & COREFILTER_MAPPED_SHARED) != 0);
}
else if (mapping_anon_p)
- return (filterflags & COREFILTER_ANON_SHARED) != 0;
+ dump_p = (filterflags & COREFILTER_ANON_SHARED) != 0;
else
- return (filterflags & COREFILTER_MAPPED_SHARED) != 0;
+ dump_p = (filterflags & COREFILTER_MAPPED_SHARED) != 0;
}
+
+ /* Even if we decided that we shouldn't dump this mapping, we still
+ have to check whether (a) the user wants us to dump mappings
+ containing an ELF header, and (b) the mapping in question
+ contains an ELF header. If (a) and (b) are true, then we should
+ dump this mapping.
+
+ A mapping contains an ELF header if it is a private mapping, its
+ offset is zero, and its first word is ELFMAG. */
+ if (!dump_p && private_p && offset == 0
+ && (filterflags & COREFILTER_ELF_HEADERS) != 0)
+ {
+ /* Let's check if we have an ELF header. */
+ gdb::unique_xmalloc_ptr<char> header;
+ int errcode;
+
+ /* Useful define specifying the size of the ELF magical
+ header. */
+#ifndef SELFMAG
+#define SELFMAG 4
+#endif
+
+ /* Read the first SELFMAG bytes and check if it is ELFMAG. */
+ if (target_read_string (addr, &header, SELFMAG, &errcode) == SELFMAG
+ && errcode == 0)
+ {
+ const char *h = header.get ();
+
+ /* The EI_MAG* and ELFMAG* constants come from
+ <elf/common.h>. */
+ if (h[EI_MAG0] == ELFMAG0 && h[EI_MAG1] == ELFMAG1
+ && h[EI_MAG2] == ELFMAG2 && h[EI_MAG3] == ELFMAG3)
+ {
+ /* This mapping contains an ELF header, so we
+ should dump it. */
+ dump_p = 1;
+ }
+ }
+ }
+
+ return dump_p;
}
/* Implement the "info proc" command. */
@@ -1306,7 +1353,7 @@ linux_find_memory_regions_full (struct gdbarch *gdbarch,
if (has_anonymous)
should_dump_p = dump_mapping_p (filterflags, &v, priv,
mapping_anon_p, mapping_file_p,
- filename);
+ filename, addr, offset);
else
{
/* Older Linux kernels did not support the "Anonymous:" counter.