From patchwork Sun Mar 22 20:45:58 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergio Durigan Junior X-Patchwork-Id: 5750 Received: (qmail 84062 invoked by alias); 22 Mar 2015 20:46:03 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 84053 invoked by uid 89); 22 Mar 2015 20:46:03 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.8 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Sun, 22 Mar 2015 20:46:00 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t2MKjx9t020616 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Sun, 22 Mar 2015 16:45:59 -0400 Received: from localhost (unused-10-15-17-126.yyz.redhat.com [10.15.17.126]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t2MKjwGQ008231 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=NO); Sun, 22 Mar 2015 16:45:59 -0400 From: Sergio Durigan Junior To: Pedro Alves Cc: GDB Patches Subject: Re: [PATCH 2/2] Documentation and testcase References: <1426807358-18295-1-git-send-email-sergiodj@redhat.com> <1426807358-18295-3-git-send-email-sergiodj@redhat.com> <550C7905.9090501@redhat.com> <87mw37wfd6.fsf@redhat.com> <550C9A7C.90705@redhat.com> X-URL: http://blog.sergiodj.net Date: Sun, 22 Mar 2015 16:45:58 -0400 In-Reply-To: <550C9A7C.90705@redhat.com> (Pedro Alves's message of "Fri, 20 Mar 2015 22:09:00 +0000") Message-ID: <87wq283gmx.fsf@redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 X-IsSubscribed: yes On Friday, March 20 2015, Pedro Alves wrote: > On 03/20/2015 09:03 PM, Sergio Durigan Junior wrote: >>> > If not (I assume not), we could test that by loading the core >>> > into gdb, but _not_ the program, and then disassembling a function's >>> > address. It should fail. Then load the program and disassemble >>> > again. It should work now. Or something along those lines. >> Hm, OK. I guess I will try this approach, and if it doesn't happen then >> I will see about doing a regular file-backed mapping. > > Thanks. If that approach doesn't work (for some odd reason), let's > try to come up with another approach that still makes sure that the > program's .text is not dumped, instead of mapping some other file. > It's important that we don't regress that specifically. So, here's what I came up with. I decided to submit it here, and not create another revision of the patch series. Hope that's not a problem. (I can certainly send a separate series if you want). I am now creating corefiles that exclude the file-backed bits as well, and testing according to your instructions. I tried to make it as clear as possible in the .exp code. WDYT? diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 552da31..bbbc5d4 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -10952,6 +10952,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 . */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +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..2512761 --- /dev/null +++ b/gdb/testsuite/gdb.base/coredump-filter.exp @@ -0,0 +1,210 @@ +# 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 . + +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 + } + + # Accessing the memory the addresses point to. + gdb_test "print/x *(char *) $addr($var)" "\(\\\$$decimal = \)?" \ + "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 } { + global testfile + + # Restarting GDB without loading the binary + gdb_exit + gdb_start + + set core_loaded [gdb_core_cmd "$core" "load core"] + if { $core_loaded == -1 } { + fail "loading $core" + return + } + + gdb_test "disassemble $address" "No function contains specified address." \ + "disassemble function with corefile and without a 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] +set non_private_file_core [standard_output_file non-private-file.gcore] +set non_shared_file_core [standard_output_file non-shared-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" } } + +# We do not do file-backed mappings in the test program, but we still +# generate coredumps to test it. See the procedure 'test_disasm' +# above for details. +# +# This list is composed by: +# +# - 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 $). + +set all_file_corefiles { { "non-Private-File-Backed" "0x7b" \ + $non_private_file_core } + { "non-Shared-File-Backed" "0x77" \ + $non_shared_file_core } } + +# 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 +} + +# Getting 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) + } +} + +# Obtaining 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 + } +} + +# Generate corefiles for the "file" case. +foreach item $all_file_corefiles { + with_test_prefix "saving corefile for [lindex $item 0]" { + do_save_core [lindex $item 1] [subst [lindex $item 2]] $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 + } +} + +foreach item $all_file_corefiles { + with_test_prefix "disassembling function main for [lindex $item 0]" { + test_disasm [subst [lindex $item 2]] $main_addr + } +}