| Index: gdb/gcore.c
|
| diff --git a/gdb/gcore.c b/gdb/gcore.c
|
| index aedda412eb6771adccb86983cdb977a4c3ccd748..49f9b2204b0be2fef9630d93e2b2826d56e196d6 100644
|
| --- a/gdb/gcore.c
|
| +++ b/gdb/gcore.c
|
| @@ -1,6 +1,6 @@
|
| /* Generate a core file for the inferior process.
|
|
|
| - Copyright (C) 2001-2012 Free Software Foundation, Inc.
|
| + Copyright (C) 2001-2013 Free Software Foundation, Inc.
|
|
|
| This file is part of GDB.
|
|
|
| @@ -33,6 +33,8 @@
|
| #include <fcntl.h>
|
| #include "regcache.h"
|
| #include "regset.h"
|
| +#include "gdb_bfd.h"
|
| +#include "readline/tilde.h"
|
|
|
| /* The largest amount of memory to read from the target at once. We
|
| must throttle it to limit the amount of memory used by GDB during
|
| @@ -48,9 +50,9 @@ static int gcore_memory_sections (bfd *);
|
| Open a new bfd core file for output, and return the handle. */
|
|
|
| bfd *
|
| -create_gcore_bfd (char *filename)
|
| +create_gcore_bfd (const char *filename)
|
| {
|
| - bfd *obfd = bfd_openw (filename, default_gcore_target ());
|
| + bfd *obfd = gdb_bfd_openw (filename, default_gcore_target ());
|
|
|
| if (!obfd)
|
| error (_("Failed to open '%s' for output."), filename);
|
| @@ -74,10 +76,10 @@ write_gcore_file (bfd *obfd)
|
| /* FIXME: uweigand/2011-10-06: All architectures that support core file
|
| generation should be converted to gdbarch_make_corefile_notes; at that
|
| point, the target vector method can be removed. */
|
| - if (!gdbarch_make_corefile_notes_p (target_gdbarch))
|
| + if (!gdbarch_make_corefile_notes_p (target_gdbarch ()))
|
| note_data = target_make_corefile_notes (obfd, ¬e_size);
|
| else
|
| - note_data = gdbarch_make_corefile_notes (target_gdbarch, obfd, ¬e_size);
|
| + note_data = gdbarch_make_corefile_notes (target_gdbarch (), obfd, ¬e_size);
|
|
|
| if (note_data == NULL || note_size == 0)
|
| error (_("Target does not support core file generation."));
|
| @@ -110,7 +112,7 @@ do_bfd_delete_cleanup (void *arg)
|
| bfd *obfd = arg;
|
| const char *filename = obfd->filename;
|
|
|
| - bfd_close (arg);
|
| + gdb_bfd_unref (arg);
|
| unlink (filename);
|
| }
|
|
|
| @@ -120,8 +122,9 @@ do_bfd_delete_cleanup (void *arg)
|
| static void
|
| gcore_command (char *args, int from_tty)
|
| {
|
| - struct cleanup *old_chain;
|
| - char *corefilename, corefilename_buffer[40];
|
| + struct cleanup *filename_chain;
|
| + struct cleanup *bfd_chain;
|
| + char *corefilename;
|
| bfd *obfd;
|
|
|
| /* No use generating a corefile without a target process. */
|
| @@ -129,13 +132,13 @@ gcore_command (char *args, int from_tty)
|
| noprocess ();
|
|
|
| if (args && *args)
|
| - corefilename = args;
|
| + corefilename = tilde_expand (args);
|
| else
|
| {
|
| /* Default corefile name is "core.PID". */
|
| - sprintf (corefilename_buffer, "core.%d", PIDGET (inferior_ptid));
|
| - corefilename = corefilename_buffer;
|
| + corefilename = xstrprintf ("core.%d", ptid_get_pid (inferior_ptid));
|
| }
|
| + filename_chain = make_cleanup (xfree, corefilename);
|
|
|
| if (info_verbose)
|
| fprintf_filtered (gdb_stdout,
|
| @@ -145,16 +148,17 @@ gcore_command (char *args, int from_tty)
|
| obfd = create_gcore_bfd (corefilename);
|
|
|
| /* Need a cleanup that will close and delete the file. */
|
| - old_chain = make_cleanup (do_bfd_delete_cleanup, obfd);
|
| + bfd_chain = make_cleanup (do_bfd_delete_cleanup, obfd);
|
|
|
| /* Call worker function. */
|
| write_gcore_file (obfd);
|
|
|
| /* Succeeded. */
|
| - fprintf_filtered (gdb_stdout, "Saved corefile %s\n", corefilename);
|
| + discard_cleanups (bfd_chain);
|
| + gdb_bfd_unref (obfd);
|
|
|
| - discard_cleanups (old_chain);
|
| - bfd_close (obfd);
|
| + fprintf_filtered (gdb_stdout, "Saved corefile %s\n", corefilename);
|
| + do_cleanups (filename_chain);
|
| }
|
|
|
| static unsigned long
|
| @@ -164,7 +168,7 @@ default_gcore_mach (void)
|
| return 0;
|
| #else
|
|
|
| - const struct bfd_arch_info *bfdarch = gdbarch_bfd_arch_info (target_gdbarch);
|
| + const struct bfd_arch_info *bfdarch = gdbarch_bfd_arch_info (target_gdbarch ());
|
|
|
| if (bfdarch != NULL)
|
| return bfdarch->mach;
|
| @@ -178,7 +182,7 @@ default_gcore_mach (void)
|
| static enum bfd_architecture
|
| default_gcore_arch (void)
|
| {
|
| - const struct bfd_arch_info *bfdarch = gdbarch_bfd_arch_info (target_gdbarch);
|
| + const struct bfd_arch_info *bfdarch = gdbarch_bfd_arch_info (target_gdbarch ());
|
|
|
| if (bfdarch != NULL)
|
| return bfdarch->arch;
|
| @@ -192,8 +196,8 @@ static const char *
|
| default_gcore_target (void)
|
| {
|
| /* The gdbarch may define a target to use for core files. */
|
| - if (gdbarch_gcore_bfd_target_p (target_gdbarch))
|
| - return gdbarch_gcore_bfd_target (target_gdbarch);
|
| + if (gdbarch_gcore_bfd_target_p (target_gdbarch ()))
|
| + return gdbarch_gcore_bfd_target (target_gdbarch ());
|
|
|
| /* Otherwise, try to fall back to the exec_bfd target. This will probably
|
| not work for non-ELF targets. */
|
| @@ -378,9 +382,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;
|
| @@ -389,18 +396,18 @@ 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)
|
| {
|
| fprintf_filtered (gdb_stdout, "Ignore segment, %s bytes at %s\n",
|
| - plongest (size), paddress (target_gdbarch, vaddr));
|
| + plongest (size), paddress (target_gdbarch (), vaddr));
|
| }
|
|
|
| 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. */
|
| @@ -423,8 +430,9 @@ gcore_create_callback (CORE_ADDR vaddr, unsigned long size,
|
|
|
| This BFD was synthesized from reading target memory,
|
| we don't want to omit that. */
|
| - if (((vaddr >= start && vaddr + size <= end)
|
| - || (start >= vaddr && end <= vaddr + size))
|
| + if (objfile->separate_debug_objfile_backlink == NULL
|
| + && ((vaddr >= start && vaddr + size <= end)
|
| + || (start >= vaddr && end <= vaddr + size))
|
| && !(bfd_get_file_flags (abfd) & BFD_IN_MEMORY))
|
| {
|
| flags &= ~(SEC_LOAD | SEC_HAS_CONTENTS);
|
| @@ -432,10 +440,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
|
| @@ -452,7 +462,7 @@ gcore_create_callback (CORE_ADDR vaddr, unsigned long size,
|
| if (info_verbose)
|
| {
|
| fprintf_filtered (gdb_stdout, "Save segment, %s bytes at %s\n",
|
| - plongest (size), paddress (target_gdbarch, vaddr));
|
| + plongest (size), paddress (target_gdbarch (), vaddr));
|
| }
|
|
|
| bfd_set_section_size (obfd, osec, size);
|
| @@ -476,6 +486,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);
|
| @@ -485,6 +499,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;
|
| @@ -497,6 +512,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. */
|
| @@ -505,6 +521,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;
|
| @@ -541,7 +558,7 @@ gcore_copy_callback (bfd *obfd, asection *osec, void *ignored)
|
| warning (_("Memory read failed for corefile "
|
| "section, %s bytes at %s."),
|
| plongest (size),
|
| - paddress (target_gdbarch, bfd_section_vma (obfd, osec)));
|
| + paddress (target_gdbarch (), bfd_section_vma (obfd, osec)));
|
| break;
|
| }
|
| if (!bfd_set_section_contents (obfd, osec, memhunk, offset, size))
|
| @@ -562,8 +579,8 @@ static int
|
| gcore_memory_sections (bfd *obfd)
|
| {
|
| /* Try gdbarch method first, then fall back to target method. */
|
| - if (!gdbarch_find_memory_regions_p (target_gdbarch)
|
| - || gdbarch_find_memory_regions (target_gdbarch,
|
| + if (!gdbarch_find_memory_regions_p (target_gdbarch ())
|
| + || gdbarch_find_memory_regions (target_gdbarch (),
|
| gcore_create_callback, obfd) != 0)
|
| {
|
| if (target_find_memory_regions (gcore_create_callback, obfd) != 0)
|
|
|