From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10686 invoked by alias); 21 Nov 2009 00:11:27 -0000 Received: (qmail 10677 invoked by uid 22791); 21 Nov 2009 00:11:26 -0000 X-SWARE-Spam-Status: No, hits=-2.4 required=5.0 tests=AWL,BAYES_00,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 21 Nov 2009 00:10:30 +0000 Received: (qmail 31485 invoked from network); 21 Nov 2009 00:10:29 -0000 Received: from unknown (HELO digraph.polyomino.org.uk) (joseph@127.0.0.2) by mail.codesourcery.com with ESMTPA; 21 Nov 2009 00:10:29 -0000 Received: from jsm28 (helo=localhost) by digraph.polyomino.org.uk with local-esmtp (Exim 4.69) (envelope-from ) id 1NBdYZ-0002iI-P6 for gdb-patches@sourceware.org; Sat, 21 Nov 2009 00:10:27 +0000 Date: Sat, 21 Nov 2009 00:11:00 -0000 From: "Joseph S. Myers" To: gdb-patches@sourceware.org Subject: Fix Solaris gcore / shared libraries interaction Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII 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: 2009-11/txt/msg00454.txt.bz2 With some versions of the Solaris 10 dynamic linker, if you create a core file with GDB's gcore command and then load that core file into GDB, you get warnings of the form warning: Can't read pathname for load map: I/O error. on loading the core file. The problem is that the l_name pointer for the dynamic linker, in the process's link map, points into the read-only text segment of ld.so (specifically, it points to the SONAME in the string table), and GDB excludes this text segment when creating the core dump. Normally excluding text segments of shared libraries is fine, but in this case it causes the above problems reloading the core dump. This patch fixes the problem by arranging for read-only memory not to be excluded from core dumps if it contains the l_name value. OK to commit? 2009-11-21 Joseph Myers * gcore.c: Include solib.h. (gcore_create_callback): Call solib_keep_data_in_core when considering not saving memory in core file. * solib-svr4.c (svr4_keep_data_in_core): New. (_initialize_svr4_solib): Initialize svr4_so_ops.keep_data_in_core. * solib.c (solib_keep_data_in_core): New. * solib.h (solib_keep_data_in_core): Declare. * solist.h (struct target_so_ops): Add keep_data_in_core. Index: gdb/gcore.c =================================================================== RCS file: /cvs/src/src/gdb/gcore.c,v retrieving revision 1.35 diff -u -p -r1.35 gcore.c --- gdb/gcore.c 22 Oct 2009 19:36:06 -0000 1.35 +++ gdb/gcore.c 20 Nov 2009 22:14:47 -0000 @@ -24,6 +24,7 @@ #include "inferior.h" #include "gdbcore.h" #include "objfiles.h" +#include "solib.h" #include "symfile.h" #include "arch-utils.h" #include "completer.h" @@ -389,7 +390,7 @@ gcore_create_callback (CORE_ADDR vaddr, return 0; } - if (write == 0) + if (write == 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. */ Index: gdb/solib-svr4.c =================================================================== RCS file: /cvs/src/src/gdb/solib-svr4.c,v retrieving revision 1.107 diff -u -p -r1.107 solib-svr4.c --- gdb/solib-svr4.c 10 Nov 2009 21:36:48 -0000 1.107 +++ gdb/solib-svr4.c 20 Nov 2009 22:14:47 -0000 @@ -866,6 +866,50 @@ solib_svr4_r_ldsomap (struct svr4_info * ptr_type); } +/* On Solaris systems with some versions of the dynamic linker, + ld.so's l_name pointer points to the SONAME in the string table + rather than into writable memory. So that GDB can find shared + libraries when loading a core file generated by gcore, ensure that + memory areas containing the l_name string are saved in the core + file. */ + +static int +svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size) +{ + struct svr4_info *info; + CORE_ADDR ldsomap; + struct so_list *new; + struct cleanup *old_chain; + struct link_map_offsets *lmo; + CORE_ADDR lm_name; + + info = get_svr4_info (); + + info->debug_base = 0; + locate_base (info); + if (!info->debug_base) + return 0; + + ldsomap = solib_svr4_r_ldsomap (info); + if (!ldsomap) + return 0; + + lmo = svr4_fetch_link_map_offsets (); + new = XZALLOC (struct so_list); + old_chain = make_cleanup (xfree, new); + new->lm_info = xmalloc (sizeof (struct lm_info)); + make_cleanup (xfree, new->lm_info); + new->lm_info->l_addr = (CORE_ADDR)-1; + new->lm_info->lm_addr = ldsomap; + new->lm_info->lm = xzalloc (lmo->link_map_size); + make_cleanup (xfree, new->lm_info->lm); + read_memory (ldsomap, new->lm_info->lm, lmo->link_map_size); + lm_name = LM_NAME (new); + do_cleanups (old_chain); + + return (lm_name >= vaddr && lm_name < vaddr + size); +} + /* LOCAL FUNCTION @@ -1918,4 +1962,5 @@ _initialize_svr4_solib (void) svr4_so_ops.bfd_open = solib_bfd_open; svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol; svr4_so_ops.same = svr4_same; + svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core; } Index: gdb/solib.c =================================================================== RCS file: /cvs/src/src/gdb/solib.c,v retrieving revision 1.128 diff -u -p -r1.128 solib.c --- gdb/solib.c 19 Oct 2009 09:51:42 -0000 1.128 +++ gdb/solib.c 20 Nov 2009 22:14:47 -0000 @@ -948,6 +948,23 @@ solib_name_from_address (struct program_ return (0); } +/* Return whether the data starting at VADDR, size SIZE, must be kept + in a core file for shared libraries loaded before "gcore" is used + to be handled correctly when the core file is loaded. This only + applies when the section would otherwise not be kept in the core + file (in particular, for readonly sections). */ + +int +solib_keep_data_in_core (CORE_ADDR vaddr, unsigned long size) +{ + struct target_so_ops *ops = solib_ops (target_gdbarch); + + if (ops->keep_data_in_core) + return ops->keep_data_in_core (vaddr, size); + else + return 0; +} + /* Called by free_all_symtabs */ void Index: gdb/solib.h =================================================================== RCS file: /cvs/src/src/gdb/solib.h,v retrieving revision 1.25 diff -u -p -r1.25 solib.h --- gdb/solib.h 19 Oct 2009 09:51:42 -0000 1.25 +++ gdb/solib.h 20 Nov 2009 22:14:47 -0000 @@ -52,6 +52,14 @@ extern char *solib_name_from_address (st extern int solib_contains_address_p (const struct so_list *, CORE_ADDR); +/* Return whether the data starting at VADDR, size SIZE, must be kept + in a core file for shared libraries loaded before "gcore" is used + to be handled correctly when the core file is loaded. This only + applies when the section would otherwise not be kept in the core + file (in particular, for readonly sections). */ + +extern int solib_keep_data_in_core (CORE_ADDR vaddr, unsigned long size); + /* Return 1 if PC lies in the dynamic symbol resolution code of the run time loader. */ Index: gdb/solist.h =================================================================== RCS file: /cvs/src/src/gdb/solist.h,v retrieving revision 1.26 diff -u -p -r1.26 solist.h --- gdb/solist.h 19 Oct 2009 09:51:42 -0000 1.26 +++ gdb/solist.h 20 Nov 2009 22:14:47 -0000 @@ -126,6 +126,14 @@ struct target_so_ops Falls back to using strcmp on so_original_name field when set to NULL. */ int (*same) (struct so_list *gdb, struct so_list *inferior); + + /* Return whether a region of memory must be kept in a core file + for shared libraries loaded before "gcore" is used to be + handled correctly when the core file is loaded. This only + applies when the section would otherwise not be kept in the + core file (in particular, for readonly sections). */ + int (*keep_data_in_core) (CORE_ADDR vaddr, + unsigned long size); }; /* Free the memory associated with a (so_list *). */ -- Joseph S. Myers joseph@codesourcery.com