/* Generate a core file for the inferior process.
- Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 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 2 of the License, or
+ 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,
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, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "elf-bfd.h"
#include "gdb_assert.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
+ generate-core-file for programs with large resident data. */
+#define MAX_COPY_BYTES (1024 * 1024)
+
static char *default_gcore_target (void);
static enum bfd_architecture default_gcore_arch (void);
static unsigned long default_gcore_mach (void);
/* Create the note section. */
if (note_data != NULL && note_size != 0)
{
- note_sec = bfd_make_section_anyway (obfd, "note0");
+ note_sec = bfd_make_section_anyway_with_flags (obfd, "note0",
+ SEC_HAS_CONTENTS
+ | SEC_READONLY
+ | SEC_ALLOC);
if (note_sec == NULL)
error (_("Failed to create 'note' section for corefile: %s"),
bfd_errmsg (bfd_get_error ()));
bfd_set_section_vma (obfd, note_sec, 0);
- bfd_set_section_flags (obfd, note_sec,
- SEC_HAS_CONTENTS | SEC_READONLY | SEC_ALLOC);
bfd_set_section_alignment (obfd, note_sec, 0);
bfd_set_section_size (obfd, note_sec, note_size);
}
#if 1 /* See if this even matters... */
return 0;
#else
-#ifdef TARGET_ARCHITECTURE
- const struct bfd_arch_info *bfdarch = TARGET_ARCHITECTURE;
+
+ const struct bfd_arch_info *bfdarch = gdbarch_bfd_arch_info (current_gdbarch);
if (bfdarch != NULL)
return bfdarch->mach;
-#endif /* TARGET_ARCHITECTURE */
if (exec_bfd == NULL)
error (_("Can't find default bfd machine type (need execfile)."));
static enum bfd_architecture
default_gcore_arch (void)
{
-#ifdef TARGET_ARCHITECTURE
- const struct bfd_arch_info * bfdarch = TARGET_ARCHITECTURE;
+ const struct bfd_arch_info * bfdarch = gdbarch_bfd_arch_info
+ (current_gdbarch);
if (bfdarch != NULL)
return bfdarch->arch;
-#endif
if (exec_bfd == NULL)
error (_("Can't find bfd architecture for corefile (need execfile)."));
/* Save frame pointer of TOS frame. */
*top = get_frame_base (fi);
/* If current stack pointer is more "inner", use that instead. */
- if (INNER_THAN (read_sp (), *top))
- *top = read_sp ();
+ if (gdbarch_inner_than (get_frame_arch (fi), get_frame_sp (fi), *top))
+ *top = get_frame_sp (fi);
/* Find prev-most frame. */
while ((tmp_fi = get_prev_frame (fi)) != NULL)
static int
derive_heap_segment (bfd *abfd, bfd_vma *bottom, bfd_vma *top)
{
+ struct objfile *sbrk_objf;
+ struct gdbarch *gdbarch;
bfd_vma top_of_data_memory = 0;
bfd_vma top_of_heap = 0;
bfd_size_type sec_size;
/* Now get the top-of-heap by calling sbrk in the inferior. */
if (lookup_minimal_symbol ("sbrk", NULL, NULL) != NULL)
{
- sbrk = find_function_in_inferior ("sbrk");
+ sbrk = find_function_in_inferior ("sbrk", &sbrk_objf);
if (sbrk == NULL)
return 0;
}
else if (lookup_minimal_symbol ("_sbrk", NULL, NULL) != NULL)
{
- sbrk = find_function_in_inferior ("_sbrk");
+ sbrk = find_function_in_inferior ("_sbrk", &sbrk_objf);
if (sbrk == NULL)
return 0;
}
else
return 0;
- zero = value_from_longest (builtin_type_int, 0);
+ gdbarch = get_objfile_arch (sbrk_objf);
+ zero = value_from_longest (builtin_type (gdbarch)->builtin_int, 0);
gdb_assert (zero);
sbrk = call_function_by_hand (sbrk, 1, &zero);
if (sbrk == NULL)
if (info_verbose)
{
fprintf_filtered (gdb_stdout, "Ignore segment, %s bytes at 0x%s\n",
- paddr_d (size), paddr_nz (vaddr));
+ plongest (size), paddr_nz (vaddr));
}
return 0;
asection *asec = objsec->the_bfd_section;
bfd_vma align = (bfd_vma) 1 << bfd_get_section_alignment (abfd,
asec);
- bfd_vma start = objsec->addr & -align;
- bfd_vma end = (objsec->endaddr + align - 1) & -align;
+ bfd_vma start = obj_section_addr (objsec) & -align;
+ bfd_vma end = (obj_section_endaddr (objsec) + align - 1) & -align;
/* Match if either the entire memory region lies inside the
section (i.e. a mapping covering some pages of a large
segment) or the entire section lies inside the memory region
&& !(bfd_get_file_flags (abfd) & BFD_IN_MEMORY))
{
flags &= ~SEC_LOAD;
+ flags |= SEC_NEVER_LOAD;
goto keep; /* break out of two nested for loops */
}
}
else
flags |= SEC_DATA;
- osec = bfd_make_section_anyway (obfd, "load");
+ osec = bfd_make_section_anyway_with_flags (obfd, "load", flags);
if (osec == NULL)
{
warning (_("Couldn't make gcore segment: %s"),
if (info_verbose)
{
fprintf_filtered (gdb_stdout, "Save segment, %s bytes at 0x%s\n",
- paddr_d (size), paddr_nz (vaddr));
+ plongest (size), paddr_nz (vaddr));
}
bfd_set_section_size (obfd, osec, size);
bfd_set_section_vma (obfd, osec, vaddr);
bfd_section_lma (obfd, osec) = 0; /* ??? bfd_set_section_lma? */
- bfd_set_section_flags (obfd, osec, flags);
return 0;
}
int size = bfd_section_size (ibfd, isec);
int ret;
- ret = (*func) (objsec->addr, bfd_section_size (ibfd, isec),
+ ret = (*func) (obj_section_addr (objsec), bfd_section_size (ibfd, isec),
1, /* All sections will be readable. */
(flags & SEC_READONLY) == 0, /* Writable. */
(flags & SEC_CODE) != 0, /* Executable. */
static void
gcore_copy_callback (bfd *obfd, asection *osec, void *ignored)
{
- bfd_size_type size = bfd_section_size (obfd, osec);
+ bfd_size_type size, total_size = bfd_section_size (obfd, osec);
+ file_ptr offset = 0;
struct cleanup *old_chain = NULL;
void *memhunk;
if (strncmp ("load", bfd_section_name (obfd, osec), 4) != 0)
return;
+ size = min (total_size, MAX_COPY_BYTES);
memhunk = xmalloc (size);
/* ??? This is crap since xmalloc should never return NULL. */
if (memhunk == NULL)
error (_("Not enough memory to create corefile."));
old_chain = make_cleanup (xfree, memhunk);
- if (target_read_memory (bfd_section_vma (obfd, osec),
- memhunk, size) != 0)
- warning (_("Memory read failed for corefile section, %s bytes at 0x%s."),
- paddr_d (size), paddr (bfd_section_vma (obfd, osec)));
- if (!bfd_set_section_contents (obfd, osec, memhunk, 0, size))
- warning (_("Failed to write corefile contents (%s)."),
- bfd_errmsg (bfd_get_error ()));
+ while (total_size > 0)
+ {
+ if (size > total_size)
+ size = total_size;
+
+ if (target_read_memory (bfd_section_vma (obfd, osec) + offset,
+ memhunk, size) != 0)
+ {
+ warning (_("Memory read failed for corefile section, %s bytes at 0x%s."),
+ plongest (size), paddr (bfd_section_vma (obfd, osec)));
+ break;
+ }
+ if (!bfd_set_section_contents (obfd, osec, memhunk, offset, size))
+ {
+ warning (_("Failed to write corefile contents (%s)."),
+ bfd_errmsg (bfd_get_error ()));
+ break;
+ }
+
+ total_size -= size;
+ offset += size;
+ }
do_cleanups (old_chain); /* Frees MEMHUNK. */
}
return 1;
}
+/* Provide a prototype to silence -Wmissing-prototypes. */
+extern initialize_file_ftype _initialize_gcore;
+
void
_initialize_gcore (void)
{
- add_com ("generate-core-file", class_files, gcore_command,
- "\
+ add_com ("generate-core-file", class_files, gcore_command, _("\
Save a core file with the current state of the debugged process.\n\
-Argument is optional filename. Default filename is 'core.<process_id>'.");
+Argument is optional filename. Default filename is 'core.<process_id>'."));
add_com_alias ("gcore", "generate-core-file", class_files, 1);
exec_set_find_memory_regions (objfile_find_memory_regions);