This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 2/2] Documentation and testcase


This patch implements the testcase and the documentation bits for the
feature.  It will be merged with the first patch when everything is
approved, and I will push a single commit with the whole feature.

The testcase makes sure that, based on different types of corefiles,
we can or cannot access certain memory regions.  There is also a test
to make sure that we can or cannot disassemble the main function, also
depending on which pages a corefile contains.

The documentation, which has already been approved by Eli, explains
how to use the new feature.  However, I included a NEWS entry this
time, because I think it is worth mentioning this feature there.

Changes from v4:

  - Added tests to make sure that, when loading a corefile without a
    binary on GDB, disassembling the main function works or not
    depending on the type of corefile used.

gdb/ChangeLog:
2015-03-24  Sergio Durigan Junior  <sergiodj@redhat.com>

	* NEWS: Mention the possibility of using the
	'/proc/PID/coredump_filter' file when generating a corefile.
	Mention new command 'set use-coredump-filter'.

gdb/doc/ChangeLog:
2015-03-24  Sergio Durigan Junior  <sergiodj@redhat.com>

	PR corefiles/16092
	* gdb.texinfo (gcore): Mention new command 'set
	use-coredump-filter'.
	(set use-coredump-filter): Document new command.

gdb/testsuite/ChangeLog:
2015-03-24  Sergio Durigan Junior  <sergiodj@redhat.com>

	PR corefiles/16092
	* gdb.base/coredump-filter.c: New file.
	* gdb.base/coredump-filter.exp: Likewise.
---
 gdb/NEWS                                   |   8 ++
 gdb/doc/gdb.texinfo                        |  33 +++++
 gdb/testsuite/gdb.base/coredump-filter.c   |  61 +++++++++
 gdb/testsuite/gdb.base/coredump-filter.exp | 198 +++++++++++++++++++++++++++++
 4 files changed, 300 insertions(+)
 create mode 100644 gdb/testsuite/gdb.base/coredump-filter.c
 create mode 100644 gdb/testsuite/gdb.base/coredump-filter.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index 3fa33c9..96fb85c 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,14 @@
 
 *** Changes since GDB 7.9
 
+* GDB now honors the content of the file /proc/PID/coredump_filter
+  (PID is the process ID) on GNU/Linux systems.  This file can be used
+  to specify the types of memory mappings that will be included in a
+  corefile.  For more information, please refer to the manual page of
+  "core(5)".  GDB also has a new command: "set use-coredump-filter
+  on|off".  It allows to set whether GDB will read the content of the
+  /proc/PID/coredump_filter file when generating a corefile.
+
 * GDB has two new commands: "set serial parity odd|even|none" and
   "show serial parity".  These allows to set or show parity for the
   remote serial I/O.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index c03ecb0..f750ed5 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -10951,6 +10951,39 @@ specified, the file name defaults to @file{core.@var{pid}}, where
 
 Note that this command is implemented only for some systems (as of
 this writing, @sc{gnu}/Linux, FreeBSD, Solaris, and S390).
+
+On @sc{gnu}/Linux, this command can take into account the value of the
+file @file{/proc/@var{pid}/coredump_filter} when generating the core
+dump (@pxref{set use-coredump-filter}).
+
+@kindex set use-coredump-filter
+@anchor{set use-coredump-filter}
+@item set use-coredump-filter on
+@itemx set use-coredump-filter off
+Enable or disable the use of the file
+@file{/proc/@var{pid}/coredump_filter} when generating core dump
+files.  This file is used by the Linux kernel to decide what types of
+memory mappings will be dumped or ignored when generating a core dump
+file.  @var{pid} is the process ID of a currently running process.
+
+To make use of this feature, you have to write in the
+@file{/proc/@var{pid}/coredump_filter} file a value, in hexadecimal,
+which is a bit mask representing the memory mapping types.  If a bit
+is set in the bit mask, then the memory mappings of the corresponding
+types will be dumped; otherwise, they will be ignored.  This
+configuration is inherited by child processes.  For more information
+about the bits that can be set in the
+@file{/proc/@var{pid}/coredump_filter} file, please refer to the
+manpage of @code{core(5)}.
+
+By default, this option is @code{on}.  If this option is turned
+@code{off}, @value{GDBN} does not read the @file{coredump_filter} file
+and instead uses the same default value as the Linux kernel in order
+to decide which pages will be dumped in the core dump file.  This
+value is currently @code{0x33}, which means that bits @code{0}
+(anonymous private mappings), @code{1} (anonymous shared mappings),
+@code{4} (ELF headers) and @code{5} (private huge pages) are active.
+This will cause these memory mappings to be dumped automatically.
 @end table
 
 @node Character Sets
diff --git a/gdb/testsuite/gdb.base/coredump-filter.c b/gdb/testsuite/gdb.base/coredump-filter.c
new file mode 100644
index 0000000..192c469
--- /dev/null
+++ b/gdb/testsuite/gdb.base/coredump-filter.c
@@ -0,0 +1,61 @@
+/* Copyright 2015 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <string.h>
+
+static void *
+do_mmap (void *addr, size_t size, int prot, int flags, int fd, off_t offset)
+{
+  void *ret = mmap (addr, size, prot, flags, fd, offset);
+
+  assert (ret != NULL);
+  return ret;
+}
+
+int
+main (int argc, char *argv[])
+{
+  const size_t size = 10;
+  const int default_prot = PROT_READ | PROT_WRITE;
+  char *private_anon, *shared_anon;
+  char *dont_dump;
+  int i;
+
+  private_anon = do_mmap (NULL, size, default_prot,
+			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  memset (private_anon, 0x11, size);
+
+  shared_anon = do_mmap (NULL, size, default_prot,
+			 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+  memset (shared_anon, 0x22, size);
+
+  dont_dump = do_mmap (NULL, size, default_prot,
+		       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  memset (dont_dump, 0x55, size);
+  i = madvise (dont_dump, size, MADV_DONTDUMP);
+  assert_perror (errno);
+  assert (i == 0);
+
+  return 0; /* break-here */
+}
diff --git a/gdb/testsuite/gdb.base/coredump-filter.exp b/gdb/testsuite/gdb.base/coredump-filter.exp
new file mode 100644
index 0000000..f3203be
--- /dev/null
+++ b/gdb/testsuite/gdb.base/coredump-filter.exp
@@ -0,0 +1,198 @@
+# Copyright 2015 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
+    untested "could not compile test program"
+    return -1
+}
+
+if { ![runto_main] } {
+    untested "could not run to main"
+    return -1
+}
+
+gdb_breakpoint [gdb_get_line_number "break-here"]
+gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+proc do_save_core { filter_flag core ipid } {
+    verbose -log "writing $filter_flag to /proc/$ipid/coredump_filter"
+
+    remote_exec target "sh -c \"echo $filter_flag > /proc/$ipid/coredump_filter\""
+
+    # Generate a corefile.
+    gdb_gcore_cmd "$core" "save corefile"
+}
+
+proc do_load_and_test_core { core var working_var working_value } {
+    global hex decimal addr
+
+    set core_loaded [gdb_core_cmd "$core" "load core"]
+    if { $core_loaded == -1 } {
+	fail "loading $core"
+	return
+    }
+
+    # Access the memory the addresses point to.
+    gdb_test "print/x *(char *) $addr($var)" "\(\\\$$decimal = <error: \)?Cannot access memory at address $hex\(>\)?" \
+	"printing $var when core is loaded (should not work)"
+    gdb_test "print/x *(char *) $addr($working_var)" " = $working_value.*" \
+	"print/x *$working_var ( = $working_value)"
+}
+
+# We do not do file-backed mappings in the test program, but it is
+# important to test this anyway.  One way of performing the test is to
+# load GDB with a corefile but without a binary, and then ask for the
+# disassemble of a function (i.e., the binary's .text section).  GDB
+# should fail in this case.  However, it must succeed if the binary is
+# provided along with the corefile.  This is what we test here.
+
+proc test_disasm { core address should_fail } {
+    global testfile hex
+
+    # Restart GDB without loading the binary.
+    with_test_prefix "no binary" {
+	gdb_exit
+	gdb_start
+
+	set core_loaded [gdb_core_cmd "$core" "load core"]
+	if { $core_loaded == -1 } {
+	    fail "loading $core"
+	    return
+	}
+
+	if { $should_fail == 1 } {
+	    gdb_test "x/i \$pc" "=> $hex:\tCannot access memory at address $hex" \
+		"disassemble function with corefile and without a binary"
+	} else {
+	    gdb_test "x/i \$pc" "=> $hex:\t\[^C\].*" \
+		"disassemble function with corefile and without a binary"
+	}
+    }
+
+    with_test_prefix "with binary" {
+	clean_restart $testfile
+
+	set core_loaded [gdb_core_cmd "$core" "load core"]
+	if { $core_loaded == -1 } {
+	    fail "loading $core"
+	    return
+	}
+
+	gdb_test "disassemble $address" "Dump of assembler code for function.*" \
+	    "disassemble function with corefile and with a binary"
+    }
+}
+
+set non_private_anon_core [standard_output_file non-private-anon.gcore]
+set non_shared_anon_core [standard_output_file non-shared-anon.gcore]
+# A corefile without {private,shared} {anonymous,file-backed} pages
+set non_private_shared_anon_file_core [standard_output_file non-private-shared-anon-file.gcore]
+set dont_dump_core [standard_output_file dont-dump.gcore]
+
+# We will generate a few corefiles.
+#
+# This list is composed by sub-lists, and their elements are (in
+# order):
+#
+# - name of the test
+# - hexadecimal value to be put in the /proc/PID/coredump_filter file
+# - name of the variable that contains the name of the corefile to be
+#   generated (including the initial $).
+# - name of the variable in the C source code that points to the
+#   memory mapping that will NOT be present in the corefile.
+# - name of a variable in the C source code that points to a memory
+#   mapping that WILL be present in the corefile
+# - corresponding value expected for the above variable
+#
+# This list refers to the corefiles generated by MAP_ANONYMOUS in the
+# test program.
+
+set all_anon_corefiles { { "non-Private-Anonymous" "0x7e" \
+			       $non_private_anon_core \
+			       "private_anon" \
+			       "shared_anon" "0x22" }
+    { "non-Shared-Anonymous" "0x7d" \
+	  $non_shared_anon_core "shared_anon" \
+	  "private_anon" "0x11" }
+    { "DoNotDump" "0x33" \
+	  $dont_dump_core "dont_dump" \
+	  "shared_anon" "0x22" } }
+
+# If corefile loading is not supported, we do not even try to run the
+# tests.
+set core_supported [gdb_gcore_cmd "$non_private_anon_core" "save a corefile"]
+if { !$core_supported } {
+    untested "corefile generation is not supported"
+    return -1
+}
+
+# Get the inferior's PID.
+set infpid ""
+gdb_test_multiple "info inferiors" "getting inferior pid" {
+    -re "process \($decimal\).*\r\n$gdb_prompt $" {
+	set infpid $expect_out(1,string)
+    }
+}
+
+# Get the main function's address.
+set main_addr ""
+gdb_test_multiple "print/x &main" "getting main's address" {
+    -re "$decimal = \($hex\)\r\n$gdb_prompt $" {
+	set main_addr $expect_out(1,string)
+    }
+}
+
+# Obtain the address of each variable that will be checked on each
+# case.
+foreach item $all_anon_corefiles {
+    foreach name [list [lindex $item 3] [lindex $item 4]] {
+	set test "print/x $name"
+	gdb_test_multiple $test $test {
+	    -re " = \($hex\)\r\n$gdb_prompt $" {
+		set addr($name) $expect_out(1,string)
+	    }
+	}
+    }
+}
+
+# Generate corefiles for the "anon" case.
+foreach item $all_anon_corefiles {
+    with_test_prefix "saving corefile for [lindex $item 0]" {
+	do_save_core [lindex $item 1] [subst [lindex $item 2]] $infpid
+    }
+}
+
+with_test_prefix "saving corefile for non-Private-Shared-Anon-File" {
+    do_save_core "0x60" $non_private_shared_anon_file_core $infpid
+}
+
+clean_restart $testfile
+
+foreach item $all_anon_corefiles {
+    with_test_prefix "loading and testing corefile for [lindex $item 0]" {
+	do_load_and_test_core [subst [lindex $item 2]] [lindex $item 3] \
+	    [lindex $item 4] [lindex $item 5]
+    }
+
+    with_test_prefix "disassembling function main for [lindex $item 0]" {
+	test_disasm [subst [lindex $item 2]] $main_addr 0
+    }
+}
+
+with_test_prefix "loading and testing corefile for non-Private-Shared-Anon-File" {
+    test_disasm $non_private_shared_anon_file_core $main_addr 1
+}
-- 
1.9.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]