1b725ae77Skettenis /* Generate a core file for the inferior process.
2b725ae77Skettenis
3b725ae77Skettenis Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4b725ae77Skettenis
5b725ae77Skettenis This file is part of GDB.
6b725ae77Skettenis
7b725ae77Skettenis This program is free software; you can redistribute it and/or modify
8b725ae77Skettenis it under the terms of the GNU General Public License as published by
9b725ae77Skettenis the Free Software Foundation; either version 2 of the License, or
10b725ae77Skettenis (at your option) any later version.
11b725ae77Skettenis
12b725ae77Skettenis This program is distributed in the hope that it will be useful,
13b725ae77Skettenis but WITHOUT ANY WARRANTY; without even the implied warranty of
14b725ae77Skettenis MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15b725ae77Skettenis GNU General Public License for more details.
16b725ae77Skettenis
17b725ae77Skettenis You should have received a copy of the GNU General Public License
18b725ae77Skettenis along with this program; if not, write to the Free Software
19b725ae77Skettenis Foundation, Inc., 59 Temple Place - Suite 330,
20b725ae77Skettenis Boston, MA 02111-1307, USA. */
21b725ae77Skettenis
22b725ae77Skettenis #include "defs.h"
23b725ae77Skettenis #include "elf-bfd.h"
24b725ae77Skettenis #include "infcall.h"
25b725ae77Skettenis #include "inferior.h"
26b725ae77Skettenis #include "gdbcore.h"
27b725ae77Skettenis #include "objfiles.h"
28b725ae77Skettenis #include "symfile.h"
29b725ae77Skettenis
30b725ae77Skettenis #include "cli/cli-decode.h"
31b725ae77Skettenis
32b725ae77Skettenis #include "gdb_assert.h"
33b725ae77Skettenis
34b725ae77Skettenis static char *default_gcore_target (void);
35b725ae77Skettenis static enum bfd_architecture default_gcore_arch (void);
36b725ae77Skettenis static unsigned long default_gcore_mach (void);
37b725ae77Skettenis static int gcore_memory_sections (bfd *);
38b725ae77Skettenis
39b725ae77Skettenis /* Generate a core file from the inferior process. */
40b725ae77Skettenis
41b725ae77Skettenis static void
gcore_command(char * args,int from_tty)42b725ae77Skettenis gcore_command (char *args, int from_tty)
43b725ae77Skettenis {
44b725ae77Skettenis struct cleanup *old_chain;
45b725ae77Skettenis char *corefilename, corefilename_buffer[40];
46b725ae77Skettenis asection *note_sec = NULL;
47b725ae77Skettenis bfd *obfd;
48b725ae77Skettenis void *note_data = NULL;
49b725ae77Skettenis int note_size = 0;
50b725ae77Skettenis
51b725ae77Skettenis /* No use generating a corefile without a target process. */
52b725ae77Skettenis if (!target_has_execution)
53b725ae77Skettenis noprocess ();
54b725ae77Skettenis
55b725ae77Skettenis if (args && *args)
56b725ae77Skettenis corefilename = args;
57b725ae77Skettenis else
58b725ae77Skettenis {
59b725ae77Skettenis /* Default corefile name is "core.PID". */
60b725ae77Skettenis sprintf (corefilename_buffer, "core.%d", PIDGET (inferior_ptid));
61b725ae77Skettenis corefilename = corefilename_buffer;
62b725ae77Skettenis }
63b725ae77Skettenis
64b725ae77Skettenis if (info_verbose)
65b725ae77Skettenis fprintf_filtered (gdb_stdout,
66b725ae77Skettenis "Opening corefile '%s' for output.\n", corefilename);
67b725ae77Skettenis
68b725ae77Skettenis /* Open the output file. */
69b725ae77Skettenis obfd = bfd_openw (corefilename, default_gcore_target ());
70b725ae77Skettenis if (!obfd)
71b725ae77Skettenis error ("Failed to open '%s' for output.", corefilename);
72b725ae77Skettenis
73b725ae77Skettenis /* Need a cleanup that will close the file (FIXME: delete it?). */
74b725ae77Skettenis old_chain = make_cleanup_bfd_close (obfd);
75b725ae77Skettenis
76b725ae77Skettenis bfd_set_format (obfd, bfd_core);
77b725ae77Skettenis bfd_set_arch_mach (obfd, default_gcore_arch (), default_gcore_mach ());
78b725ae77Skettenis
79b725ae77Skettenis /* An external target method must build the notes section. */
80b725ae77Skettenis note_data = target_make_corefile_notes (obfd, ¬e_size);
81b725ae77Skettenis
82b725ae77Skettenis /* Create the note section. */
83b725ae77Skettenis if (note_data != NULL && note_size != 0)
84b725ae77Skettenis {
85b725ae77Skettenis note_sec = bfd_make_section_anyway (obfd, "note0");
86b725ae77Skettenis if (note_sec == NULL)
87b725ae77Skettenis error ("Failed to create 'note' section for corefile: %s",
88b725ae77Skettenis bfd_errmsg (bfd_get_error ()));
89b725ae77Skettenis
90b725ae77Skettenis bfd_set_section_vma (obfd, note_sec, 0);
91b725ae77Skettenis bfd_set_section_flags (obfd, note_sec,
92b725ae77Skettenis SEC_HAS_CONTENTS | SEC_READONLY | SEC_ALLOC);
93b725ae77Skettenis bfd_set_section_alignment (obfd, note_sec, 0);
94b725ae77Skettenis bfd_set_section_size (obfd, note_sec, note_size);
95b725ae77Skettenis }
96b725ae77Skettenis
97b725ae77Skettenis /* Now create the memory/load sections. */
98b725ae77Skettenis if (gcore_memory_sections (obfd) == 0)
99b725ae77Skettenis error ("gcore: failed to get corefile memory sections from target.");
100b725ae77Skettenis
101b725ae77Skettenis /* Write out the contents of the note section. */
102b725ae77Skettenis if (note_data != NULL && note_size != 0)
103b725ae77Skettenis {
104b725ae77Skettenis if (!bfd_set_section_contents (obfd, note_sec, note_data, 0, note_size))
105b725ae77Skettenis warning ("writing note section (%s)", bfd_errmsg (bfd_get_error ()));
106b725ae77Skettenis }
107b725ae77Skettenis
108b725ae77Skettenis /* Succeeded. */
109b725ae77Skettenis fprintf_filtered (gdb_stdout, "Saved corefile %s\n", corefilename);
110b725ae77Skettenis
111b725ae77Skettenis /* Clean-ups will close the output file and free malloc memory. */
112b725ae77Skettenis do_cleanups (old_chain);
113b725ae77Skettenis return;
114b725ae77Skettenis }
115b725ae77Skettenis
116b725ae77Skettenis static unsigned long
default_gcore_mach(void)117b725ae77Skettenis default_gcore_mach (void)
118b725ae77Skettenis {
119b725ae77Skettenis #if 1 /* See if this even matters... */
120b725ae77Skettenis return 0;
121b725ae77Skettenis #else
122b725ae77Skettenis #ifdef TARGET_ARCHITECTURE
123b725ae77Skettenis const struct bfd_arch_info *bfdarch = TARGET_ARCHITECTURE;
124b725ae77Skettenis
125b725ae77Skettenis if (bfdarch != NULL)
126b725ae77Skettenis return bfdarch->mach;
127b725ae77Skettenis #endif /* TARGET_ARCHITECTURE */
128b725ae77Skettenis if (exec_bfd == NULL)
129b725ae77Skettenis error ("Can't find default bfd machine type (need execfile).");
130b725ae77Skettenis
131b725ae77Skettenis return bfd_get_mach (exec_bfd);
132b725ae77Skettenis #endif /* 1 */
133b725ae77Skettenis }
134b725ae77Skettenis
135b725ae77Skettenis static enum bfd_architecture
default_gcore_arch(void)136b725ae77Skettenis default_gcore_arch (void)
137b725ae77Skettenis {
138b725ae77Skettenis #ifdef TARGET_ARCHITECTURE
139b725ae77Skettenis const struct bfd_arch_info * bfdarch = TARGET_ARCHITECTURE;
140b725ae77Skettenis
141b725ae77Skettenis if (bfdarch != NULL)
142b725ae77Skettenis return bfdarch->arch;
143b725ae77Skettenis #endif
144b725ae77Skettenis if (exec_bfd == NULL)
145b725ae77Skettenis error ("Can't find bfd architecture for corefile (need execfile).");
146b725ae77Skettenis
147b725ae77Skettenis return bfd_get_arch (exec_bfd);
148b725ae77Skettenis }
149b725ae77Skettenis
150b725ae77Skettenis static char *
default_gcore_target(void)151b725ae77Skettenis default_gcore_target (void)
152b725ae77Skettenis {
153b725ae77Skettenis /* FIXME: This may only work for ELF targets. */
154b725ae77Skettenis if (exec_bfd == NULL)
155b725ae77Skettenis return NULL;
156b725ae77Skettenis else
157b725ae77Skettenis return bfd_get_target (exec_bfd);
158b725ae77Skettenis }
159b725ae77Skettenis
160b725ae77Skettenis /* Derive a reasonable stack segment by unwinding the target stack,
161b725ae77Skettenis and store its limits in *BOTTOM and *TOP. Return non-zero if
162b725ae77Skettenis successful. */
163b725ae77Skettenis
164b725ae77Skettenis static int
derive_stack_segment(bfd_vma * bottom,bfd_vma * top)165b725ae77Skettenis derive_stack_segment (bfd_vma *bottom, bfd_vma *top)
166b725ae77Skettenis {
167b725ae77Skettenis struct frame_info *fi, *tmp_fi;
168b725ae77Skettenis
169b725ae77Skettenis gdb_assert (bottom);
170b725ae77Skettenis gdb_assert (top);
171b725ae77Skettenis
172b725ae77Skettenis /* Can't succeed without stack and registers. */
173b725ae77Skettenis if (!target_has_stack || !target_has_registers)
174b725ae77Skettenis return 0;
175b725ae77Skettenis
176b725ae77Skettenis /* Can't succeed without current frame. */
177b725ae77Skettenis fi = get_current_frame ();
178b725ae77Skettenis if (fi == NULL)
179b725ae77Skettenis return 0;
180b725ae77Skettenis
181b725ae77Skettenis /* Save frame pointer of TOS frame. */
182b725ae77Skettenis *top = get_frame_base (fi);
183b725ae77Skettenis /* If current stack pointer is more "inner", use that instead. */
184b725ae77Skettenis if (INNER_THAN (read_sp (), *top))
185b725ae77Skettenis *top = read_sp ();
186b725ae77Skettenis
187b725ae77Skettenis /* Find prev-most frame. */
188b725ae77Skettenis while ((tmp_fi = get_prev_frame (fi)) != NULL)
189b725ae77Skettenis fi = tmp_fi;
190b725ae77Skettenis
191b725ae77Skettenis /* Save frame pointer of prev-most frame. */
192b725ae77Skettenis *bottom = get_frame_base (fi);
193b725ae77Skettenis
194b725ae77Skettenis /* Now canonicalize their order, so that BOTTOM is a lower address
195b725ae77Skettenis (as opposed to a lower stack frame). */
196b725ae77Skettenis if (*bottom > *top)
197b725ae77Skettenis {
198b725ae77Skettenis bfd_vma tmp_vma;
199b725ae77Skettenis
200b725ae77Skettenis tmp_vma = *top;
201b725ae77Skettenis *top = *bottom;
202b725ae77Skettenis *bottom = tmp_vma;
203b725ae77Skettenis }
204b725ae77Skettenis
205b725ae77Skettenis return 1;
206b725ae77Skettenis }
207b725ae77Skettenis
208b725ae77Skettenis /* Derive a reasonable heap segment for ABFD by looking at sbrk and
209b725ae77Skettenis the static data sections. Store its limits in *BOTTOM and *TOP.
210b725ae77Skettenis Return non-zero if successful. */
211b725ae77Skettenis
212b725ae77Skettenis static int
derive_heap_segment(bfd * abfd,bfd_vma * bottom,bfd_vma * top)213b725ae77Skettenis derive_heap_segment (bfd *abfd, bfd_vma *bottom, bfd_vma *top)
214b725ae77Skettenis {
215b725ae77Skettenis bfd_vma top_of_data_memory = 0;
216b725ae77Skettenis bfd_vma top_of_heap = 0;
217b725ae77Skettenis bfd_size_type sec_size;
218b725ae77Skettenis struct value *zero, *sbrk;
219b725ae77Skettenis bfd_vma sec_vaddr;
220b725ae77Skettenis asection *sec;
221b725ae77Skettenis
222b725ae77Skettenis gdb_assert (bottom);
223b725ae77Skettenis gdb_assert (top);
224b725ae77Skettenis
225b725ae77Skettenis /* This function depends on being able to call a function in the
226b725ae77Skettenis inferior. */
227b725ae77Skettenis if (!target_has_execution)
228b725ae77Skettenis return 0;
229b725ae77Skettenis
230b725ae77Skettenis /* The following code assumes that the link map is arranged as
231b725ae77Skettenis follows (low to high addresses):
232b725ae77Skettenis
233b725ae77Skettenis ---------------------------------
234b725ae77Skettenis | text sections |
235b725ae77Skettenis ---------------------------------
236b725ae77Skettenis | data sections (including bss) |
237b725ae77Skettenis ---------------------------------
238b725ae77Skettenis | heap |
239b725ae77Skettenis --------------------------------- */
240b725ae77Skettenis
241b725ae77Skettenis for (sec = abfd->sections; sec; sec = sec->next)
242b725ae77Skettenis {
243b725ae77Skettenis if (bfd_get_section_flags (abfd, sec) & SEC_DATA
244b725ae77Skettenis || strcmp (".bss", bfd_section_name (abfd, sec)) == 0)
245b725ae77Skettenis {
246b725ae77Skettenis sec_vaddr = bfd_get_section_vma (abfd, sec);
247*11efff7fSkettenis sec_size = bfd_get_section_size (sec);
248b725ae77Skettenis if (sec_vaddr + sec_size > top_of_data_memory)
249b725ae77Skettenis top_of_data_memory = sec_vaddr + sec_size;
250b725ae77Skettenis }
251b725ae77Skettenis }
252b725ae77Skettenis
253b725ae77Skettenis /* Now get the top-of-heap by calling sbrk in the inferior. */
254b725ae77Skettenis if (lookup_minimal_symbol ("sbrk", NULL, NULL) != NULL)
255b725ae77Skettenis {
256b725ae77Skettenis sbrk = find_function_in_inferior ("sbrk");
257b725ae77Skettenis if (sbrk == NULL)
258b725ae77Skettenis return 0;
259b725ae77Skettenis }
260b725ae77Skettenis else if (lookup_minimal_symbol ("_sbrk", NULL, NULL) != NULL)
261b725ae77Skettenis {
262b725ae77Skettenis sbrk = find_function_in_inferior ("_sbrk");
263b725ae77Skettenis if (sbrk == NULL)
264b725ae77Skettenis return 0;
265b725ae77Skettenis }
266b725ae77Skettenis else
267b725ae77Skettenis return 0;
268b725ae77Skettenis
269b725ae77Skettenis zero = value_from_longest (builtin_type_int, 0);
270b725ae77Skettenis gdb_assert (zero);
271b725ae77Skettenis sbrk = call_function_by_hand (sbrk, 1, &zero);
272b725ae77Skettenis if (sbrk == NULL)
273b725ae77Skettenis return 0;
274b725ae77Skettenis top_of_heap = value_as_long (sbrk);
275b725ae77Skettenis
276b725ae77Skettenis /* Return results. */
277b725ae77Skettenis if (top_of_heap > top_of_data_memory)
278b725ae77Skettenis {
279b725ae77Skettenis *bottom = top_of_data_memory;
280b725ae77Skettenis *top = top_of_heap;
281b725ae77Skettenis return 1;
282b725ae77Skettenis }
283b725ae77Skettenis
284b725ae77Skettenis /* No additional heap space needs to be saved. */
285b725ae77Skettenis return 0;
286b725ae77Skettenis }
287b725ae77Skettenis
288b725ae77Skettenis static void
make_output_phdrs(bfd * obfd,asection * osec,void * ignored)289b725ae77Skettenis make_output_phdrs (bfd *obfd, asection *osec, void *ignored)
290b725ae77Skettenis {
291b725ae77Skettenis int p_flags = 0;
292b725ae77Skettenis int p_type;
293b725ae77Skettenis
294b725ae77Skettenis /* FIXME: these constants may only be applicable for ELF. */
295b725ae77Skettenis if (strncmp (bfd_section_name (obfd, osec), "load", 4) == 0)
296b725ae77Skettenis p_type = PT_LOAD;
297b725ae77Skettenis else
298b725ae77Skettenis p_type = PT_NOTE;
299b725ae77Skettenis
300b725ae77Skettenis p_flags |= PF_R; /* Segment is readable. */
301b725ae77Skettenis if (!(bfd_get_section_flags (obfd, osec) & SEC_READONLY))
302b725ae77Skettenis p_flags |= PF_W; /* Segment is writable. */
303b725ae77Skettenis if (bfd_get_section_flags (obfd, osec) & SEC_CODE)
304b725ae77Skettenis p_flags |= PF_X; /* Segment is executable. */
305b725ae77Skettenis
306b725ae77Skettenis bfd_record_phdr (obfd, p_type, 1, p_flags, 0, 0, 0, 0, 1, &osec);
307b725ae77Skettenis }
308b725ae77Skettenis
309b725ae77Skettenis static int
gcore_create_callback(CORE_ADDR vaddr,unsigned long size,int read,int write,int exec,void * data)310b725ae77Skettenis gcore_create_callback (CORE_ADDR vaddr, unsigned long size,
311b725ae77Skettenis int read, int write, int exec, void *data)
312b725ae77Skettenis {
313b725ae77Skettenis bfd *obfd = data;
314b725ae77Skettenis asection *osec;
315b725ae77Skettenis flagword flags = SEC_ALLOC | SEC_HAS_CONTENTS | SEC_LOAD;
316b725ae77Skettenis
317b725ae77Skettenis /* If the memory segment has no permissions set, ignore it, otherwise
318b725ae77Skettenis when we later try to access it for read/write, we'll get an error
319b725ae77Skettenis or jam the kernel. */
320b725ae77Skettenis if (read == 0 && write == 0 && exec == 0)
321b725ae77Skettenis {
322b725ae77Skettenis if (info_verbose)
323b725ae77Skettenis {
324b725ae77Skettenis fprintf_filtered (gdb_stdout, "Ignore segment, %s bytes at 0x%s\n",
325b725ae77Skettenis paddr_d (size), paddr_nz (vaddr));
326b725ae77Skettenis }
327b725ae77Skettenis
328b725ae77Skettenis return 0;
329b725ae77Skettenis }
330b725ae77Skettenis
331b725ae77Skettenis if (write == 0)
332b725ae77Skettenis {
333b725ae77Skettenis /* See if this region of memory lies inside a known file on disk.
334b725ae77Skettenis If so, we can avoid copying its contents by clearing SEC_LOAD. */
335b725ae77Skettenis struct objfile *objfile;
336b725ae77Skettenis struct obj_section *objsec;
337b725ae77Skettenis
338b725ae77Skettenis ALL_OBJSECTIONS (objfile, objsec)
339b725ae77Skettenis {
340b725ae77Skettenis bfd *abfd = objfile->obfd;
341b725ae77Skettenis asection *asec = objsec->the_bfd_section;
342b725ae77Skettenis bfd_vma align = (bfd_vma) 1 << bfd_get_section_alignment (abfd,
343b725ae77Skettenis asec);
344b725ae77Skettenis bfd_vma start = objsec->addr & -align;
345b725ae77Skettenis bfd_vma end = (objsec->endaddr + align - 1) & -align;
346b725ae77Skettenis /* Match if either the entire memory region lies inside the
347b725ae77Skettenis section (i.e. a mapping covering some pages of a large
348b725ae77Skettenis segment) or the entire section lies inside the memory region
349b725ae77Skettenis (i.e. a mapping covering multiple small sections).
350b725ae77Skettenis
351b725ae77Skettenis This BFD was synthesized from reading target memory,
352b725ae77Skettenis we don't want to omit that. */
353b725ae77Skettenis if (((vaddr >= start && vaddr + size <= end)
354b725ae77Skettenis || (start >= vaddr && end <= vaddr + size))
355b725ae77Skettenis && !(bfd_get_file_flags (abfd) & BFD_IN_MEMORY))
356b725ae77Skettenis {
357b725ae77Skettenis flags &= ~SEC_LOAD;
358b725ae77Skettenis goto keep; /* break out of two nested for loops */
359b725ae77Skettenis }
360b725ae77Skettenis }
361b725ae77Skettenis
362b725ae77Skettenis keep:
363b725ae77Skettenis flags |= SEC_READONLY;
364b725ae77Skettenis }
365b725ae77Skettenis
366b725ae77Skettenis if (exec)
367b725ae77Skettenis flags |= SEC_CODE;
368b725ae77Skettenis else
369b725ae77Skettenis flags |= SEC_DATA;
370b725ae77Skettenis
371b725ae77Skettenis osec = bfd_make_section_anyway (obfd, "load");
372b725ae77Skettenis if (osec == NULL)
373b725ae77Skettenis {
374b725ae77Skettenis warning ("Couldn't make gcore segment: %s",
375b725ae77Skettenis bfd_errmsg (bfd_get_error ()));
376b725ae77Skettenis return 1;
377b725ae77Skettenis }
378b725ae77Skettenis
379b725ae77Skettenis if (info_verbose)
380b725ae77Skettenis {
381b725ae77Skettenis fprintf_filtered (gdb_stdout, "Save segment, %s bytes at 0x%s\n",
382b725ae77Skettenis paddr_d (size), paddr_nz (vaddr));
383b725ae77Skettenis }
384b725ae77Skettenis
385b725ae77Skettenis bfd_set_section_size (obfd, osec, size);
386b725ae77Skettenis bfd_set_section_vma (obfd, osec, vaddr);
387b725ae77Skettenis bfd_section_lma (obfd, osec) = 0; /* ??? bfd_set_section_lma? */
388b725ae77Skettenis bfd_set_section_flags (obfd, osec, flags);
389b725ae77Skettenis return 0;
390b725ae77Skettenis }
391b725ae77Skettenis
392b725ae77Skettenis static int
objfile_find_memory_regions(int (* func)(CORE_ADDR,unsigned long,int,int,int,void *),void * obfd)393b725ae77Skettenis objfile_find_memory_regions (int (*func) (CORE_ADDR, unsigned long,
394b725ae77Skettenis int, int, int, void *),
395b725ae77Skettenis void *obfd)
396b725ae77Skettenis {
397b725ae77Skettenis /* Use objfile data to create memory sections. */
398b725ae77Skettenis struct objfile *objfile;
399b725ae77Skettenis struct obj_section *objsec;
400b725ae77Skettenis bfd_vma temp_bottom, temp_top;
401b725ae77Skettenis
402b725ae77Skettenis /* Call callback function for each objfile section. */
403b725ae77Skettenis ALL_OBJSECTIONS (objfile, objsec)
404b725ae77Skettenis {
405b725ae77Skettenis bfd *ibfd = objfile->obfd;
406b725ae77Skettenis asection *isec = objsec->the_bfd_section;
407b725ae77Skettenis flagword flags = bfd_get_section_flags (ibfd, isec);
408b725ae77Skettenis int ret;
409b725ae77Skettenis
410b725ae77Skettenis if ((flags & SEC_ALLOC) || (flags & SEC_LOAD))
411b725ae77Skettenis {
412b725ae77Skettenis int size = bfd_section_size (ibfd, isec);
413b725ae77Skettenis int ret;
414b725ae77Skettenis
415b725ae77Skettenis ret = (*func) (objsec->addr, bfd_section_size (ibfd, isec),
416b725ae77Skettenis 1, /* All sections will be readable. */
417b725ae77Skettenis (flags & SEC_READONLY) == 0, /* Writable. */
418b725ae77Skettenis (flags & SEC_CODE) != 0, /* Executable. */
419b725ae77Skettenis obfd);
420b725ae77Skettenis if (ret != 0)
421b725ae77Skettenis return ret;
422b725ae77Skettenis }
423b725ae77Skettenis }
424b725ae77Skettenis
425b725ae77Skettenis /* Make a stack segment. */
426b725ae77Skettenis if (derive_stack_segment (&temp_bottom, &temp_top))
427b725ae77Skettenis (*func) (temp_bottom, temp_top - temp_bottom,
428b725ae77Skettenis 1, /* Stack section will be readable. */
429b725ae77Skettenis 1, /* Stack section will be writable. */
430b725ae77Skettenis 0, /* Stack section will not be executable. */
431b725ae77Skettenis obfd);
432b725ae77Skettenis
433b725ae77Skettenis /* Make a heap segment. */
434b725ae77Skettenis if (derive_heap_segment (exec_bfd, &temp_bottom, &temp_top))
435b725ae77Skettenis (*func) (temp_bottom, temp_top - temp_bottom,
436b725ae77Skettenis 1, /* Heap section will be readable. */
437b725ae77Skettenis 1, /* Heap section will be writable. */
438b725ae77Skettenis 0, /* Heap section will not be executable. */
439b725ae77Skettenis obfd);
440b725ae77Skettenis
441b725ae77Skettenis return 0;
442b725ae77Skettenis }
443b725ae77Skettenis
444b725ae77Skettenis static void
gcore_copy_callback(bfd * obfd,asection * osec,void * ignored)445b725ae77Skettenis gcore_copy_callback (bfd *obfd, asection *osec, void *ignored)
446b725ae77Skettenis {
447b725ae77Skettenis bfd_size_type size = bfd_section_size (obfd, osec);
448b725ae77Skettenis struct cleanup *old_chain = NULL;
449b725ae77Skettenis void *memhunk;
450b725ae77Skettenis
451b725ae77Skettenis /* Read-only sections are marked; we don't have to copy their contents. */
452b725ae77Skettenis if ((bfd_get_section_flags (obfd, osec) & SEC_LOAD) == 0)
453b725ae77Skettenis return;
454b725ae77Skettenis
455b725ae77Skettenis /* Only interested in "load" sections. */
456b725ae77Skettenis if (strncmp ("load", bfd_section_name (obfd, osec), 4) != 0)
457b725ae77Skettenis return;
458b725ae77Skettenis
459b725ae77Skettenis memhunk = xmalloc (size);
460b725ae77Skettenis /* ??? This is crap since xmalloc should never return NULL. */
461b725ae77Skettenis if (memhunk == NULL)
462b725ae77Skettenis error ("Not enough memory to create corefile.");
463b725ae77Skettenis old_chain = make_cleanup (xfree, memhunk);
464b725ae77Skettenis
465b725ae77Skettenis if (target_read_memory (bfd_section_vma (obfd, osec),
466b725ae77Skettenis memhunk, size) != 0)
467b725ae77Skettenis warning ("Memory read failed for corefile section, %s bytes at 0x%s\n",
468b725ae77Skettenis paddr_d (size), paddr (bfd_section_vma (obfd, osec)));
469b725ae77Skettenis if (!bfd_set_section_contents (obfd, osec, memhunk, 0, size))
470b725ae77Skettenis warning ("Failed to write corefile contents (%s).",
471b725ae77Skettenis bfd_errmsg (bfd_get_error ()));
472b725ae77Skettenis
473b725ae77Skettenis do_cleanups (old_chain); /* Frees MEMHUNK. */
474b725ae77Skettenis }
475b725ae77Skettenis
476b725ae77Skettenis static int
gcore_memory_sections(bfd * obfd)477b725ae77Skettenis gcore_memory_sections (bfd *obfd)
478b725ae77Skettenis {
479b725ae77Skettenis if (target_find_memory_regions (gcore_create_callback, obfd) != 0)
480b725ae77Skettenis return 0; /* FIXME: error return/msg? */
481b725ae77Skettenis
482b725ae77Skettenis /* Record phdrs for section-to-segment mapping. */
483b725ae77Skettenis bfd_map_over_sections (obfd, make_output_phdrs, NULL);
484b725ae77Skettenis
485b725ae77Skettenis /* Copy memory region contents. */
486b725ae77Skettenis bfd_map_over_sections (obfd, gcore_copy_callback, NULL);
487b725ae77Skettenis
488b725ae77Skettenis return 1;
489b725ae77Skettenis }
490b725ae77Skettenis
491b725ae77Skettenis void
_initialize_gcore(void)492b725ae77Skettenis _initialize_gcore (void)
493b725ae77Skettenis {
494b725ae77Skettenis add_com ("generate-core-file", class_files, gcore_command,
495b725ae77Skettenis "\
496b725ae77Skettenis Save a core file with the current state of the debugged process.\n\
497b725ae77Skettenis Argument is optional filename. Default filename is 'core.<process_id>'.");
498b725ae77Skettenis
499b725ae77Skettenis add_com_alias ("gcore", "generate-core-file", class_files, 1);
500b725ae77Skettenis exec_set_find_memory_regions (objfile_find_memory_regions);
501b725ae77Skettenis }
502