From de18c1d81e0722779ce942110fb271e94db9635b Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Tue, 1 Dec 2009 22:46:15 +0000 Subject: [PATCH] * 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. --- gdb/ChangeLog | 12 ++++++++++++ gdb/gcore.c | 3 ++- gdb/solib-svr4.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ gdb/solib.c | 17 +++++++++++++++++ gdb/solib.h | 8 ++++++++ gdb/solist.h | 8 ++++++++ 6 files changed, 92 insertions(+), 1 deletion(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 2cf92a9a799..613db8031a5 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,15 @@ +2009-12-01 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. + 2009-11-30 Joseph Myers * configure: Regenerate. diff --git a/gdb/gcore.c b/gdb/gcore.c index d1f8b4933cb..6d6ca47d146 100644 --- a/gdb/gcore.c +++ b/gdb/gcore.c @@ -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, unsigned long size, 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. */ diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index 21055f678d6..4bc459c6c11 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -866,6 +866,50 @@ solib_svr4_r_ldsomap (struct svr4_info *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; } diff --git a/gdb/solib.c b/gdb/solib.c index 6ad22fed2d5..e563512a991 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -948,6 +948,23 @@ solib_name_from_address (struct program_space *pspace, CORE_ADDR address) 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 diff --git a/gdb/solib.h b/gdb/solib.h index fee8d1c4434..c12de944e7b 100644 --- a/gdb/solib.h +++ b/gdb/solib.h @@ -52,6 +52,14 @@ extern char *solib_name_from_address (struct program_space *, CORE_ADDR); 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. */ diff --git a/gdb/solist.h b/gdb/solist.h index 4c164e64834..4e8e88b9ce6 100644 --- a/gdb/solist.h +++ b/gdb/solist.h @@ -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 *). */ -- 2.30.2