From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10616 invoked by alias); 31 Jul 2012 13:21:58 -0000 Received: (qmail 10608 invoked by uid 22791); 31 Jul 2012 13:21:56 -0000 X-SWARE-Spam-Status: No, hits=-5.5 required=5.0 tests=AWL,BAYES_00,FAKE_REPLY_C,KHOP_RCVD_UNTRUST,RCVD_IN_DNSWL_HI,RCVD_IN_HOSTKARMA_W,SPF_HELO_PASS,TW_BJ,TW_XS,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 31 Jul 2012 13:21:36 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q6VDLZVI012956 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 31 Jul 2012 09:21:36 -0400 Received: from host2.jankratochvil.net (ovpn-116-33.ams2.redhat.com [10.36.116.33]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q6VDLSet016212 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO); Tue, 31 Jul 2012 09:21:31 -0400 Date: Tue, 31 Jul 2012 13:21:00 -0000 From: Jan Kratochvil To: Jean-Marc Saffroy Cc: gdb-patches@sourceware.org Subject: Re: [PATCH] refreshed patch for PR 11804 and PR 9904 Message-ID: <20120731132119.GA19247@host2.jankratochvil.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-07/txt/msg00797.txt.bz2 Hi Jean-Marc, On Sun, 29 Jul 2012 19:11:12 +0200, Jean-Marc Saffroy wrote: > I'm not sure what kind you expect, so I'll let you write them. :-) OK, done. On Sun, 29 Jul 2012 19:35:00 +0200, Jean-Marc Saffroy wrote: > Of course I forgot to add a ChangeLog entry, so here it is: Updated it. Also sorry but I am still the primary author of this patch. No regressions on {x86_64,x86_64-m32,i686}-fedorarawhide-linux-gnu and with gdbserver. I will check it in in some time. While it would be nice for 7.5 I think it is too late for it. Thanks, Jan 2012-07-31 Jan Kratochvil Jean-Marc Saffroy PR 11804 * defs.h (find_memory_region_ftype): New comment. New arg modified. * fbsd-nat.c (fbsd_find_memory_regions): Add the passed modified value. * gcore.c (gcore_create_callback): New function comment. Add modified parameter. Only write modified regions. Set SEC_READONLY exactly according to MODIFIED. (objfile_find_memory_regions): Ignore separate debug info files. Ass the passed modified value to FUNC. * gnu-nat.c (gnu_find_memory_regions): Add the passed modified value. * linux-tdep.c (linux_find_memory_regions): Try to reads smaps file first. New variables modified and has_anonymous. Parse the lines of smaps file. Add the passed MODIFIED value to FUNC. * procfs.c (find_memory_regions_callback): Add the passed modified value. gdb/testsuite/ 2012-07-31 Jan Kratochvil Jean-Marc Saffroy PR 11804 * gdb.base/gcore-relro.exp: New file. * gdb.base/gcore-relro-main.c: New file. * gdb.base/gcore-relro-lib.c: New file. diff --git a/gdb/defs.h b/gdb/defs.h index 7be99a2..de34740 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -362,9 +362,14 @@ extern void init_source_path (void); /* From exec.c */ +/* Process memory area starting at ADDR with length SIZE. Area is readable iff + READ is non-zero, writable if WRITE is non-zero, executable if EXEC is + non-zero. Area is possibly changed against its original file based copy if + MODIFIED is non-zero. DATA is passed without changes from a caller. */ + typedef int (*find_memory_region_ftype) (CORE_ADDR addr, unsigned long size, int read, int write, int exec, - void *data); + int modified, void *data); /* Take over the 'find_mapped_memory' vector from exec.c. */ extern void exec_set_find_memory_regions diff --git a/gdb/fbsd-nat.c b/gdb/fbsd-nat.c index b3e4fab..4a8a509 100644 --- a/gdb/fbsd-nat.c +++ b/gdb/fbsd-nat.c @@ -131,8 +131,9 @@ fbsd_find_memory_regions (find_memory_region_ftype func, void *obfd) exec ? 'x' : '-'); } - /* Invoke the callback function to create the corefile segment. */ - func (start, size, read, write, exec, obfd); + /* Invoke the callback function to create the corefile segment. + Pass MODIFIED as true, we do not know the real modification state. */ + func (start, size, read, write, exec, 1, obfd); } do_cleanups (cleanup); diff --git a/gdb/gcore.c b/gdb/gcore.c index a45e787..3c8e2f4 100644 --- a/gdb/gcore.c +++ b/gdb/gcore.c @@ -379,9 +379,12 @@ make_output_phdrs (bfd *obfd, asection *osec, void *ignored) bfd_record_phdr (obfd, p_type, 1, p_flags, 0, 0, 0, 0, 1, &osec); } +/* find_memory_region_ftype implementation. DATA is 'bfd *' for the core file + GDB is creating. */ + static int -gcore_create_callback (CORE_ADDR vaddr, unsigned long size, - int read, int write, int exec, void *data) +gcore_create_callback (CORE_ADDR vaddr, unsigned long size, int read, + int write, int exec, int modified, void *data) { bfd *obfd = data; asection *osec; @@ -390,7 +393,7 @@ gcore_create_callback (CORE_ADDR vaddr, unsigned long size, /* If the memory segment has no permissions set, ignore it, otherwise when we later try to access it for read/write, we'll get an error or jam the kernel. */ - if (read == 0 && write == 0 && exec == 0) + if (read == 0 && write == 0 && exec == 0 && modified == 0) { if (info_verbose) { @@ -401,7 +404,7 @@ gcore_create_callback (CORE_ADDR vaddr, unsigned long size, return 0; } - if (write == 0 && !solib_keep_data_in_core (vaddr, size)) + if (write == 0 && modified == 0 && !solib_keep_data_in_core (vaddr, size)) { /* See if this region of memory lies inside a known file on disk. If so, we can avoid copying its contents by clearing SEC_LOAD. */ @@ -433,10 +436,12 @@ gcore_create_callback (CORE_ADDR vaddr, unsigned long size, } } - keep: - flags |= SEC_READONLY; + keep:; } + if (write == 0) + flags |= SEC_READONLY; + if (exec) flags |= SEC_CODE; else @@ -477,6 +482,10 @@ objfile_find_memory_regions (find_memory_region_ftype func, void *obfd) asection *isec = objsec->the_bfd_section; flagword flags = bfd_get_section_flags (ibfd, isec); + /* Separate debug info files are irrelevant for gcore. */ + if (objfile->separate_debug_objfile_backlink != NULL) + continue; + if ((flags & SEC_ALLOC) || (flags & SEC_LOAD)) { int size = bfd_section_size (ibfd, isec); @@ -486,6 +495,7 @@ objfile_find_memory_regions (find_memory_region_ftype func, void *obfd) 1, /* All sections will be readable. */ (flags & SEC_READONLY) == 0, /* Writable. */ (flags & SEC_CODE) != 0, /* Executable. */ + 1, /* MODIFIED is unknown, pass it as true. */ obfd); if (ret != 0) return ret; @@ -498,6 +508,7 @@ objfile_find_memory_regions (find_memory_region_ftype func, void *obfd) 1, /* Stack section will be readable. */ 1, /* Stack section will be writable. */ 0, /* Stack section will not be executable. */ + 1, /* Stack section will be modified. */ obfd); /* Make a heap segment. */ @@ -506,6 +517,7 @@ objfile_find_memory_regions (find_memory_region_ftype func, void *obfd) 1, /* Heap section will be readable. */ 1, /* Heap section will be writable. */ 0, /* Heap section will not be executable. */ + 1, /* Heap section will be modified. */ obfd); return 0; diff --git a/gdb/gnu-nat.c b/gdb/gnu-nat.c index 0c45f20..5a653cf 100644 --- a/gdb/gnu-nat.c +++ b/gdb/gnu-nat.c @@ -2558,6 +2558,7 @@ gnu_find_memory_regions (find_memory_region_ftype func, void *data) last_protection & VM_PROT_READ, last_protection & VM_PROT_WRITE, last_protection & VM_PROT_EXECUTE, + 1, /* MODIFIED is unknown, pass it as true. */ data); last_region_address = region_address; last_region_end = region_address += region_length; @@ -2571,6 +2572,7 @@ gnu_find_memory_regions (find_memory_region_ftype func, void *data) last_protection & VM_PROT_READ, last_protection & VM_PROT_WRITE, last_protection & VM_PROT_EXECUTE, + 1, /* MODIFIED is unknown, pass it as true. */ data); return 0; diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index b6f2efb..65f5f97 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -547,19 +547,28 @@ linux_find_memory_regions (struct gdbarch *gdbarch, return 1; xsnprintf (filename, sizeof filename, - "/proc/%d/maps", current_inferior ()->pid); + "/proc/%d/smaps", current_inferior ()->pid); data = target_fileio_read_stralloc (filename); + if (data == NULL) + { + /* Older Linux kernels did not support /proc/PID/smaps. */ + xsnprintf (filename, sizeof filename, + "/proc/%d/maps", current_inferior ()->pid); + data = target_fileio_read_stralloc (filename); + } if (data) { struct cleanup *cleanup = make_cleanup (xfree, data); char *line; - for (line = strtok (data, "\n"); line; line = strtok (NULL, "\n")) + line = strtok (data, "\n"); + while (line) { ULONGEST addr, endaddr, offset, inode; const char *permissions, *device, *filename; size_t permissions_len, device_len; int read, write, exec; + int modified = 0, has_anonymous = 0; read_mapping (line, &addr, &endaddr, &permissions, &permissions_len, &offset, &device, &device_len, &inode, &filename); @@ -569,8 +578,35 @@ linux_find_memory_regions (struct gdbarch *gdbarch, write = (memchr (permissions, 'w', permissions_len) != 0); exec = (memchr (permissions, 'x', permissions_len) != 0); + /* Try to detect if region was modified by parsing smaps counters. */ + for (line = strtok (NULL, "\n"); + line && line[0] >= 'A' && line[0] <= 'Z'; + line = strtok (NULL, "\n")) + { + char keyword[64 + 1]; + unsigned long number; + + if (sscanf (line, "%64s%lu kB\n", keyword, &number) != 2) + { + warning (_("Error parsing {s,}maps file '%s'"), filename); + break; + } + if (strcmp (keyword, "Anonymous:") == 0) + has_anonymous = 1; + if (number != 0 && (strcmp (keyword, "Shared_Dirty:") == 0 + || strcmp (keyword, "Private_Dirty:") == 0 + || strcmp (keyword, "Swap:") == 0 + || strcmp (keyword, "Anonymous:") == 0)) + modified = 1; + } + + /* Older Linux kernels did not support the "Anonymous:" counter. + If it is missing, we can't be sure - dump all the pages. */ + if (!has_anonymous) + modified = 1; + /* Invoke the callback function to create the corefile segment. */ - func (addr, endaddr - addr, read, write, exec, obfd); + func (addr, endaddr - addr, read, write, exec, modified, obfd); } do_cleanups (cleanup); diff --git a/gdb/procfs.c b/gdb/procfs.c index 4409e5b..ee2b123 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -5074,6 +5074,7 @@ find_memory_regions_callback (struct prmap *map, (map->pr_mflags & MA_READ) != 0, (map->pr_mflags & MA_WRITE) != 0, (map->pr_mflags & MA_EXEC) != 0, + 1, /* MODIFIED is unknown, pass it as true. */ data); } diff --git a/gdb/testsuite/gdb.base/gcore-relro-lib.c b/gdb/testsuite/gdb.base/gcore-relro-lib.c new file mode 100644 index 0000000..d74b690 --- /dev/null +++ b/gdb/testsuite/gdb.base/gcore-relro-lib.c @@ -0,0 +1,21 @@ +/* Copyright 2010 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 . */ + +void +lib (void) +{ +} diff --git a/gdb/testsuite/gdb.base/gcore-relro-main.c b/gdb/testsuite/gdb.base/gcore-relro-main.c new file mode 100644 index 0000000..46b9dfe --- /dev/null +++ b/gdb/testsuite/gdb.base/gcore-relro-main.c @@ -0,0 +1,25 @@ +/* Copyright 2010 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 . */ + +extern void lib (void); + +int +main (void) +{ + lib (); + return 0; +} diff --git a/gdb/testsuite/gdb.base/gcore-relro.exp b/gdb/testsuite/gdb.base/gcore-relro.exp new file mode 100644 index 0000000..5b8d6c7 --- /dev/null +++ b/gdb/testsuite/gdb.base/gcore-relro.exp @@ -0,0 +1,78 @@ +# Copyright 2012 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 . + +if {[skip_shlib_tests]} { + return 0 +} + +standard_testfile gcore-relro-main.c +set libfile gcore-relro-lib +set srcfile_lib ${libfile}.c +set binfile_lib [standard_output_file ${libfile}.so] +set gcorefile ${binfile}.gcore +set objfile [standard_output_file ${testfile}.o] + + if { [gdb_compile_shlib ${srcdir}/${subdir}/${srcfile_lib} ${binfile_lib} {debug}] != "" + || [gdb_compile ${srcdir}/${subdir}/${srcfile} ${objfile} object {debug}] != "" } { + untested ${testfile}.exp + return -1 + } + set opts [list debug shlib=${binfile_lib} additional_flags=-Wl,-z,relro] + if { [gdb_compile ${objfile} ${binfile} executable $opts] != "" } { + unsupported "-Wl,-z,relro compilation failed" + return -1 + } + +clean_restart ${binfile} +gdb_load_shlibs ${binfile_lib} + +# Does this gdb support gcore? +set test "help gcore" +gdb_test_multiple $test $test { + -re "Undefined command: .gcore.*\r\n$gdb_prompt $" { + # gcore command not supported -- nothing to test here. + unsupported "gdb does not support gcore on this target" + return -1; + } + -re "Save a core file .*\r\n$gdb_prompt $" { + pass $test + } +} + +if ![runto lib] { + return -1 +} + +set escapedfilename [string_to_regexp ${gcorefile}] + +set test "save a corefile" +gdb_test_multiple "gcore ${gcorefile}" $test { + -re "Saved corefile ${escapedfilename}\r\n$gdb_prompt $" { + pass $test + } + -re "Can't create a corefile\r\n$gdb_prompt $" { + unsupported $test + return -1 + } +} + +# Now restart gdb and load the corefile. + +clean_restart ${binfile} +gdb_load_shlibs ${binfile_lib} + +gdb_test "core ${gcorefile}" "Core was generated by .*" "re-load generated corefile" + +gdb_test "frame" "#0 \[^\r\n\]* lib .*" "library got loaded"