198944Sobrien/* Generate a core file for the inferior process. 298944Sobrien 3130803Smarcel Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc. 4130803Smarcel 598944Sobrien This file is part of GDB. 698944Sobrien 798944Sobrien This program is free software; you can redistribute it and/or modify 898944Sobrien it under the terms of the GNU General Public License as published by 998944Sobrien the Free Software Foundation; either version 2 of the License, or 1098944Sobrien (at your option) any later version. 1198944Sobrien 1298944Sobrien This program is distributed in the hope that it will be useful, 1398944Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1498944Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1598944Sobrien GNU General Public License for more details. 1698944Sobrien 1798944Sobrien You should have received a copy of the GNU General Public License 1898944Sobrien along with this program; if not, write to the Free Software 1998944Sobrien Foundation, Inc., 59 Temple Place - Suite 330, 2098944Sobrien Boston, MA 02111-1307, USA. */ 2198944Sobrien 2298944Sobrien#include "defs.h" 23130803Smarcel#include "elf-bfd.h" 24130803Smarcel#include "infcall.h" 2598944Sobrien#include "inferior.h" 2698944Sobrien#include "gdbcore.h" 27130803Smarcel#include "objfiles.h" 2898944Sobrien#include "symfile.h" 2998944Sobrien 30130803Smarcel#include "cli/cli-decode.h" 3198944Sobrien 32130803Smarcel#include "gdb_assert.h" 3398944Sobrien 34130803Smarcelstatic char *default_gcore_target (void); 35130803Smarcelstatic enum bfd_architecture default_gcore_arch (void); 36130803Smarcelstatic unsigned long default_gcore_mach (void); 37130803Smarcelstatic int gcore_memory_sections (bfd *); 38130803Smarcel 39130803Smarcel/* Generate a core file from the inferior process. */ 40130803Smarcel 4198944Sobrienstatic void 4298944Sobriengcore_command (char *args, int from_tty) 4398944Sobrien{ 4498944Sobrien struct cleanup *old_chain; 4598944Sobrien char *corefilename, corefilename_buffer[40]; 4698944Sobrien asection *note_sec = NULL; 4798944Sobrien bfd *obfd; 4898944Sobrien void *note_data = NULL; 4998944Sobrien int note_size = 0; 5098944Sobrien 5198944Sobrien /* No use generating a corefile without a target process. */ 52130803Smarcel if (!target_has_execution) 5398944Sobrien noprocess (); 5498944Sobrien 5598944Sobrien if (args && *args) 5698944Sobrien corefilename = args; 5798944Sobrien else 5898944Sobrien { 5998944Sobrien /* Default corefile name is "core.PID". */ 6098944Sobrien sprintf (corefilename_buffer, "core.%d", PIDGET (inferior_ptid)); 6198944Sobrien corefilename = corefilename_buffer; 6298944Sobrien } 6398944Sobrien 6498944Sobrien if (info_verbose) 65130803Smarcel fprintf_filtered (gdb_stdout, 6698944Sobrien "Opening corefile '%s' for output.\n", corefilename); 6798944Sobrien 68130803Smarcel /* Open the output file. */ 69130803Smarcel obfd = bfd_openw (corefilename, default_gcore_target ()); 70130803Smarcel if (!obfd) 71130803Smarcel error ("Failed to open '%s' for output.", corefilename); 7298944Sobrien 73130803Smarcel /* Need a cleanup that will close the file (FIXME: delete it?). */ 7498944Sobrien old_chain = make_cleanup_bfd_close (obfd); 7598944Sobrien 7698944Sobrien bfd_set_format (obfd, bfd_core); 7798944Sobrien bfd_set_arch_mach (obfd, default_gcore_arch (), default_gcore_mach ()); 7898944Sobrien 79130803Smarcel /* An external target method must build the notes section. */ 80130803Smarcel note_data = target_make_corefile_notes (obfd, ¬e_size); 8198944Sobrien 82130803Smarcel /* Create the note section. */ 8398944Sobrien if (note_data != NULL && note_size != 0) 8498944Sobrien { 85130803Smarcel note_sec = bfd_make_section_anyway (obfd, "note0"); 86130803Smarcel if (note_sec == NULL) 87130803Smarcel error ("Failed to create 'note' section for corefile: %s", 8898944Sobrien bfd_errmsg (bfd_get_error ())); 8998944Sobrien 9098944Sobrien bfd_set_section_vma (obfd, note_sec, 0); 91130803Smarcel bfd_set_section_flags (obfd, note_sec, 9298944Sobrien SEC_HAS_CONTENTS | SEC_READONLY | SEC_ALLOC); 9398944Sobrien bfd_set_section_alignment (obfd, note_sec, 0); 9498944Sobrien bfd_set_section_size (obfd, note_sec, note_size); 9598944Sobrien } 9698944Sobrien 97130803Smarcel /* Now create the memory/load sections. */ 9898944Sobrien if (gcore_memory_sections (obfd) == 0) 9998944Sobrien error ("gcore: failed to get corefile memory sections from target."); 10098944Sobrien 101130803Smarcel /* Write out the contents of the note section. */ 10298944Sobrien if (note_data != NULL && note_size != 0) 10398944Sobrien { 10498944Sobrien if (!bfd_set_section_contents (obfd, note_sec, note_data, 0, note_size)) 105130803Smarcel warning ("writing note section (%s)", bfd_errmsg (bfd_get_error ())); 10698944Sobrien } 10798944Sobrien 108130803Smarcel /* Succeeded. */ 109130803Smarcel fprintf_filtered (gdb_stdout, "Saved corefile %s\n", corefilename); 11098944Sobrien 111130803Smarcel /* Clean-ups will close the output file and free malloc memory. */ 11298944Sobrien do_cleanups (old_chain); 11398944Sobrien return; 11498944Sobrien} 11598944Sobrien 11698944Sobrienstatic unsigned long 11798944Sobriendefault_gcore_mach (void) 11898944Sobrien{ 119130803Smarcel#if 1 /* See if this even matters... */ 12098944Sobrien return 0; 12198944Sobrien#else 12298944Sobrien#ifdef TARGET_ARCHITECTURE 123130803Smarcel const struct bfd_arch_info *bfdarch = TARGET_ARCHITECTURE; 12498944Sobrien 12598944Sobrien if (bfdarch != NULL) 12698944Sobrien return bfdarch->mach; 12798944Sobrien#endif /* TARGET_ARCHITECTURE */ 12898944Sobrien if (exec_bfd == NULL) 12998944Sobrien error ("Can't find default bfd machine type (need execfile)."); 13098944Sobrien 13198944Sobrien return bfd_get_mach (exec_bfd); 13298944Sobrien#endif /* 1 */ 13398944Sobrien} 13498944Sobrien 13598944Sobrienstatic enum bfd_architecture 13698944Sobriendefault_gcore_arch (void) 13798944Sobrien{ 13898944Sobrien#ifdef TARGET_ARCHITECTURE 13998944Sobrien const struct bfd_arch_info * bfdarch = TARGET_ARCHITECTURE; 14098944Sobrien 14198944Sobrien if (bfdarch != NULL) 14298944Sobrien return bfdarch->arch; 14398944Sobrien#endif 14498944Sobrien if (exec_bfd == NULL) 14598944Sobrien error ("Can't find bfd architecture for corefile (need execfile)."); 14698944Sobrien 14798944Sobrien return bfd_get_arch (exec_bfd); 14898944Sobrien} 14998944Sobrien 15098944Sobrienstatic char * 15198944Sobriendefault_gcore_target (void) 15298944Sobrien{ 153130803Smarcel /* FIXME: This may only work for ELF targets. */ 15498944Sobrien if (exec_bfd == NULL) 15598944Sobrien return NULL; 15698944Sobrien else 15798944Sobrien return bfd_get_target (exec_bfd); 15898944Sobrien} 15998944Sobrien 160130803Smarcel/* Derive a reasonable stack segment by unwinding the target stack, 161130803Smarcel and store its limits in *BOTTOM and *TOP. Return non-zero if 162130803Smarcel successful. */ 16398944Sobrien 164130803Smarcelstatic int 165130803Smarcelderive_stack_segment (bfd_vma *bottom, bfd_vma *top) 16698944Sobrien{ 16798944Sobrien struct frame_info *fi, *tmp_fi; 16898944Sobrien 169130803Smarcel gdb_assert (bottom); 170130803Smarcel gdb_assert (top); 17198944Sobrien 172130803Smarcel /* Can't succeed without stack and registers. */ 17398944Sobrien if (!target_has_stack || !target_has_registers) 174130803Smarcel return 0; 17598944Sobrien 176130803Smarcel /* Can't succeed without current frame. */ 177130803Smarcel fi = get_current_frame (); 178130803Smarcel if (fi == NULL) 179130803Smarcel return 0; 18098944Sobrien 181130803Smarcel /* Save frame pointer of TOS frame. */ 182130803Smarcel *top = get_frame_base (fi); 183130803Smarcel /* If current stack pointer is more "inner", use that instead. */ 18498944Sobrien if (INNER_THAN (read_sp (), *top)) 18598944Sobrien *top = read_sp (); 18698944Sobrien 187130803Smarcel /* Find prev-most frame. */ 18898944Sobrien while ((tmp_fi = get_prev_frame (fi)) != NULL) 18998944Sobrien fi = tmp_fi; 19098944Sobrien 191130803Smarcel /* Save frame pointer of prev-most frame. */ 192130803Smarcel *bottom = get_frame_base (fi); 19398944Sobrien 194130803Smarcel /* Now canonicalize their order, so that BOTTOM is a lower address 195130803Smarcel (as opposed to a lower stack frame). */ 19698944Sobrien if (*bottom > *top) 19798944Sobrien { 198130803Smarcel bfd_vma tmp_vma; 199130803Smarcel 20098944Sobrien tmp_vma = *top; 20198944Sobrien *top = *bottom; 20298944Sobrien *bottom = tmp_vma; 20398944Sobrien } 20498944Sobrien 205130803Smarcel return 1; 20698944Sobrien} 20798944Sobrien 208130803Smarcel/* Derive a reasonable heap segment for ABFD by looking at sbrk and 209130803Smarcel the static data sections. Store its limits in *BOTTOM and *TOP. 210130803Smarcel Return non-zero if successful. */ 211130803Smarcel 21298944Sobrienstatic int 213130803Smarcelderive_heap_segment (bfd *abfd, bfd_vma *bottom, bfd_vma *top) 21498944Sobrien{ 21598944Sobrien bfd_vma top_of_data_memory = 0; 21698944Sobrien bfd_vma top_of_heap = 0; 21798944Sobrien bfd_size_type sec_size; 21898944Sobrien struct value *zero, *sbrk; 21998944Sobrien bfd_vma sec_vaddr; 22098944Sobrien asection *sec; 22198944Sobrien 222130803Smarcel gdb_assert (bottom); 223130803Smarcel gdb_assert (top); 22498944Sobrien 225130803Smarcel /* This function depends on being able to call a function in the 226130803Smarcel inferior. */ 22798944Sobrien if (!target_has_execution) 228130803Smarcel return 0; 22998944Sobrien 230130803Smarcel /* The following code assumes that the link map is arranged as 231130803Smarcel follows (low to high addresses): 23298944Sobrien 233130803Smarcel --------------------------------- 234130803Smarcel | text sections | 235130803Smarcel --------------------------------- 236130803Smarcel | data sections (including bss) | 237130803Smarcel --------------------------------- 238130803Smarcel | heap | 239130803Smarcel --------------------------------- */ 240130803Smarcel 24198944Sobrien for (sec = abfd->sections; sec; sec = sec->next) 24298944Sobrien { 243130803Smarcel if (bfd_get_section_flags (abfd, sec) & SEC_DATA 244130803Smarcel || strcmp (".bss", bfd_section_name (abfd, sec)) == 0) 24598944Sobrien { 24698944Sobrien sec_vaddr = bfd_get_section_vma (abfd, sec); 247218822Sdim sec_size = bfd_get_section_size (sec); 24898944Sobrien if (sec_vaddr + sec_size > top_of_data_memory) 24998944Sobrien top_of_data_memory = sec_vaddr + sec_size; 25098944Sobrien } 25198944Sobrien } 252130803Smarcel 25398944Sobrien /* Now get the top-of-heap by calling sbrk in the inferior. */ 254130803Smarcel if (lookup_minimal_symbol ("sbrk", NULL, NULL) != NULL) 255130803Smarcel { 256130803Smarcel sbrk = find_function_in_inferior ("sbrk"); 257130803Smarcel if (sbrk == NULL) 258130803Smarcel return 0; 259130803Smarcel } 260130803Smarcel else if (lookup_minimal_symbol ("_sbrk", NULL, NULL) != NULL) 261130803Smarcel { 262130803Smarcel sbrk = find_function_in_inferior ("_sbrk"); 263130803Smarcel if (sbrk == NULL) 264130803Smarcel return 0; 265130803Smarcel } 266130803Smarcel else 26798944Sobrien return 0; 268130803Smarcel 269130803Smarcel zero = value_from_longest (builtin_type_int, 0); 270130803Smarcel gdb_assert (zero); 271130803Smarcel sbrk = call_function_by_hand (sbrk, 1, &zero); 272130803Smarcel if (sbrk == NULL) 27398944Sobrien return 0; 27498944Sobrien top_of_heap = value_as_long (sbrk); 27598944Sobrien 276130803Smarcel /* Return results. */ 27798944Sobrien if (top_of_heap > top_of_data_memory) 27898944Sobrien { 27998944Sobrien *bottom = top_of_data_memory; 28098944Sobrien *top = top_of_heap; 281130803Smarcel return 1; 28298944Sobrien } 28398944Sobrien 284130803Smarcel /* No additional heap space needs to be saved. */ 285130803Smarcel return 0; 28698944Sobrien} 28798944Sobrien 28898944Sobrienstatic void 28998944Sobrienmake_output_phdrs (bfd *obfd, asection *osec, void *ignored) 29098944Sobrien{ 29198944Sobrien int p_flags = 0; 29298944Sobrien int p_type; 29398944Sobrien 29498944Sobrien /* FIXME: these constants may only be applicable for ELF. */ 295130803Smarcel if (strncmp (bfd_section_name (obfd, osec), "load", 4) == 0) 29698944Sobrien p_type = PT_LOAD; 29798944Sobrien else 29898944Sobrien p_type = PT_NOTE; 29998944Sobrien 30098944Sobrien p_flags |= PF_R; /* Segment is readable. */ 30198944Sobrien if (!(bfd_get_section_flags (obfd, osec) & SEC_READONLY)) 30298944Sobrien p_flags |= PF_W; /* Segment is writable. */ 30398944Sobrien if (bfd_get_section_flags (obfd, osec) & SEC_CODE) 30498944Sobrien p_flags |= PF_X; /* Segment is executable. */ 30598944Sobrien 306130803Smarcel bfd_record_phdr (obfd, p_type, 1, p_flags, 0, 0, 0, 0, 1, &osec); 30798944Sobrien} 30898944Sobrien 309130803Smarcelstatic int 310130803Smarcelgcore_create_callback (CORE_ADDR vaddr, unsigned long size, 311130803Smarcel int read, int write, int exec, void *data) 31298944Sobrien{ 313130803Smarcel bfd *obfd = data; 31498944Sobrien asection *osec; 315130803Smarcel flagword flags = SEC_ALLOC | SEC_HAS_CONTENTS | SEC_LOAD; 31698944Sobrien 317130803Smarcel /* If the memory segment has no permissions set, ignore it, otherwise 318130803Smarcel when we later try to access it for read/write, we'll get an error 319130803Smarcel or jam the kernel. */ 320130803Smarcel if (read == 0 && write == 0 && exec == 0) 32198944Sobrien { 322130803Smarcel if (info_verbose) 323130803Smarcel { 324130803Smarcel fprintf_filtered (gdb_stdout, "Ignore segment, %s bytes at 0x%s\n", 325130803Smarcel paddr_d (size), paddr_nz (vaddr)); 326130803Smarcel } 327130803Smarcel 328130803Smarcel return 0; 32998944Sobrien } 33098944Sobrien 331130803Smarcel if (write == 0) 33298944Sobrien { 333130803Smarcel /* See if this region of memory lies inside a known file on disk. 334130803Smarcel If so, we can avoid copying its contents by clearing SEC_LOAD. */ 335130803Smarcel struct objfile *objfile; 336130803Smarcel struct obj_section *objsec; 33798944Sobrien 338130803Smarcel ALL_OBJSECTIONS (objfile, objsec) 339130803Smarcel { 340130803Smarcel bfd *abfd = objfile->obfd; 341130803Smarcel asection *asec = objsec->the_bfd_section; 342130803Smarcel bfd_vma align = (bfd_vma) 1 << bfd_get_section_alignment (abfd, 343130803Smarcel asec); 344130803Smarcel bfd_vma start = objsec->addr & -align; 345130803Smarcel bfd_vma end = (objsec->endaddr + align - 1) & -align; 346130803Smarcel /* Match if either the entire memory region lies inside the 347130803Smarcel section (i.e. a mapping covering some pages of a large 348130803Smarcel segment) or the entire section lies inside the memory region 349130803Smarcel (i.e. a mapping covering multiple small sections). 35098944Sobrien 351130803Smarcel This BFD was synthesized from reading target memory, 352130803Smarcel we don't want to omit that. */ 353130803Smarcel if (((vaddr >= start && vaddr + size <= end) 354130803Smarcel || (start >= vaddr && end <= vaddr + size)) 355130803Smarcel && !(bfd_get_file_flags (abfd) & BFD_IN_MEMORY)) 356130803Smarcel { 357130803Smarcel flags &= ~SEC_LOAD; 358130803Smarcel goto keep; /* break out of two nested for loops */ 359130803Smarcel } 360130803Smarcel } 36198944Sobrien 362130803Smarcel keep: 36398944Sobrien flags |= SEC_READONLY; 36498944Sobrien } 365130803Smarcel 36698944Sobrien if (exec) 367130803Smarcel flags |= SEC_CODE; 368130803Smarcel else 369130803Smarcel flags |= SEC_DATA; 370130803Smarcel 371130803Smarcel osec = bfd_make_section_anyway (obfd, "load"); 372130803Smarcel if (osec == NULL) 37398944Sobrien { 374130803Smarcel warning ("Couldn't make gcore segment: %s", 375130803Smarcel bfd_errmsg (bfd_get_error ())); 376130803Smarcel return 1; 37798944Sobrien } 378130803Smarcel 379130803Smarcel if (info_verbose) 38098944Sobrien { 381130803Smarcel fprintf_filtered (gdb_stdout, "Save segment, %s bytes at 0x%s\n", 382130803Smarcel paddr_d (size), paddr_nz (vaddr)); 38398944Sobrien } 38498944Sobrien 385130803Smarcel bfd_set_section_size (obfd, osec, size); 386130803Smarcel bfd_set_section_vma (obfd, osec, vaddr); 387130803Smarcel bfd_section_lma (obfd, osec) = 0; /* ??? bfd_set_section_lma? */ 388130803Smarcel bfd_set_section_flags (obfd, osec, flags); 389130803Smarcel return 0; 39098944Sobrien} 39198944Sobrien 39298944Sobrienstatic int 393130803Smarcelobjfile_find_memory_regions (int (*func) (CORE_ADDR, unsigned long, 394130803Smarcel int, int, int, void *), 39598944Sobrien void *obfd) 39698944Sobrien{ 397130803Smarcel /* Use objfile data to create memory sections. */ 39898944Sobrien struct objfile *objfile; 39998944Sobrien struct obj_section *objsec; 40098944Sobrien bfd_vma temp_bottom, temp_top; 40198944Sobrien 402130803Smarcel /* Call callback function for each objfile section. */ 40398944Sobrien ALL_OBJSECTIONS (objfile, objsec) 40498944Sobrien { 40598944Sobrien bfd *ibfd = objfile->obfd; 40698944Sobrien asection *isec = objsec->the_bfd_section; 40798944Sobrien flagword flags = bfd_get_section_flags (ibfd, isec); 40898944Sobrien int ret; 40998944Sobrien 41098944Sobrien if ((flags & SEC_ALLOC) || (flags & SEC_LOAD)) 41198944Sobrien { 41298944Sobrien int size = bfd_section_size (ibfd, isec); 41398944Sobrien int ret; 41498944Sobrien 415130803Smarcel ret = (*func) (objsec->addr, bfd_section_size (ibfd, isec), 416130803Smarcel 1, /* All sections will be readable. */ 417130803Smarcel (flags & SEC_READONLY) == 0, /* Writable. */ 418130803Smarcel (flags & SEC_CODE) != 0, /* Executable. */ 419130803Smarcel obfd); 420130803Smarcel if (ret != 0) 42198944Sobrien return ret; 42298944Sobrien } 42398944Sobrien } 42498944Sobrien 425130803Smarcel /* Make a stack segment. */ 42698944Sobrien if (derive_stack_segment (&temp_bottom, &temp_top)) 427130803Smarcel (*func) (temp_bottom, temp_top - temp_bottom, 428130803Smarcel 1, /* Stack section will be readable. */ 429130803Smarcel 1, /* Stack section will be writable. */ 430130803Smarcel 0, /* Stack section will not be executable. */ 43198944Sobrien obfd); 43298944Sobrien 43398944Sobrien /* Make a heap segment. */ 43498944Sobrien if (derive_heap_segment (exec_bfd, &temp_bottom, &temp_top)) 435130803Smarcel (*func) (temp_bottom, temp_top - temp_bottom, 436130803Smarcel 1, /* Heap section will be readable. */ 437130803Smarcel 1, /* Heap section will be writable. */ 438130803Smarcel 0, /* Heap section will not be executable. */ 43998944Sobrien obfd); 440130803Smarcel 44198944Sobrien return 0; 44298944Sobrien} 44398944Sobrien 44498944Sobrienstatic void 44598944Sobriengcore_copy_callback (bfd *obfd, asection *osec, void *ignored) 44698944Sobrien{ 44798944Sobrien bfd_size_type size = bfd_section_size (obfd, osec); 44898944Sobrien struct cleanup *old_chain = NULL; 44998944Sobrien void *memhunk; 45098944Sobrien 451130803Smarcel /* Read-only sections are marked; we don't have to copy their contents. */ 452130803Smarcel if ((bfd_get_section_flags (obfd, osec) & SEC_LOAD) == 0) 453130803Smarcel return; 45498944Sobrien 455130803Smarcel /* Only interested in "load" sections. */ 456130803Smarcel if (strncmp ("load", bfd_section_name (obfd, osec), 4) != 0) 457130803Smarcel return; 458130803Smarcel 459130803Smarcel memhunk = xmalloc (size); 460130803Smarcel /* ??? This is crap since xmalloc should never return NULL. */ 461130803Smarcel if (memhunk == NULL) 46298944Sobrien error ("Not enough memory to create corefile."); 46398944Sobrien old_chain = make_cleanup (xfree, memhunk); 46498944Sobrien 465130803Smarcel if (target_read_memory (bfd_section_vma (obfd, osec), 46698944Sobrien memhunk, size) != 0) 467130803Smarcel warning ("Memory read failed for corefile section, %s bytes at 0x%s\n", 468130803Smarcel paddr_d (size), paddr (bfd_section_vma (obfd, osec))); 46998944Sobrien if (!bfd_set_section_contents (obfd, osec, memhunk, 0, size)) 470130803Smarcel warning ("Failed to write corefile contents (%s).", 47198944Sobrien bfd_errmsg (bfd_get_error ())); 47298944Sobrien 473130803Smarcel do_cleanups (old_chain); /* Frees MEMHUNK. */ 47498944Sobrien} 47598944Sobrien 47698944Sobrienstatic int 47798944Sobriengcore_memory_sections (bfd *obfd) 47898944Sobrien{ 47998944Sobrien if (target_find_memory_regions (gcore_create_callback, obfd) != 0) 480130803Smarcel return 0; /* FIXME: error return/msg? */ 48198944Sobrien 482130803Smarcel /* Record phdrs for section-to-segment mapping. */ 48398944Sobrien bfd_map_over_sections (obfd, make_output_phdrs, NULL); 48498944Sobrien 485130803Smarcel /* Copy memory region contents. */ 48698944Sobrien bfd_map_over_sections (obfd, gcore_copy_callback, NULL); 48798944Sobrien 488130803Smarcel return 1; 48998944Sobrien} 49098944Sobrien 49198944Sobrienvoid 49298944Sobrien_initialize_gcore (void) 49398944Sobrien{ 49498944Sobrien add_com ("generate-core-file", class_files, gcore_command, 495130803Smarcel "\ 496130803SmarcelSave a core file with the current state of the debugged process.\n\ 49798944SobrienArgument is optional filename. Default filename is 'core.<process_id>'."); 49898944Sobrien 49998944Sobrien add_com_alias ("gcore", "generate-core-file", class_files, 1); 50098944Sobrien exec_set_find_memory_regions (objfile_find_memory_regions); 50198944Sobrien} 502