15796c8dcSSimon Schubert /* Generate a core file for the inferior process.
25796c8dcSSimon Schubert
3*ef5ccd6cSJohn Marino Copyright (C) 2001-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert This file is part of GDB.
65796c8dcSSimon Schubert
75796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
85796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
95796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or
105796c8dcSSimon Schubert (at your option) any later version.
115796c8dcSSimon Schubert
125796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
135796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
145796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
155796c8dcSSimon Schubert GNU General Public License for more details.
165796c8dcSSimon Schubert
175796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
185796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */
195796c8dcSSimon Schubert
205796c8dcSSimon Schubert #include "defs.h"
215796c8dcSSimon Schubert #include "elf-bfd.h"
225796c8dcSSimon Schubert #include "infcall.h"
235796c8dcSSimon Schubert #include "inferior.h"
245796c8dcSSimon Schubert #include "gdbcore.h"
255796c8dcSSimon Schubert #include "objfiles.h"
26cf7f2e2dSJohn Marino #include "solib.h"
275796c8dcSSimon Schubert #include "symfile.h"
28cf7f2e2dSJohn Marino #include "arch-utils.h"
29cf7f2e2dSJohn Marino #include "completer.h"
30cf7f2e2dSJohn Marino #include "gcore.h"
315796c8dcSSimon Schubert #include "cli/cli-decode.h"
325796c8dcSSimon Schubert #include "gdb_assert.h"
33cf7f2e2dSJohn Marino #include <fcntl.h>
34cf7f2e2dSJohn Marino #include "regcache.h"
35cf7f2e2dSJohn Marino #include "regset.h"
36*ef5ccd6cSJohn Marino #include "gdb_bfd.h"
375796c8dcSSimon Schubert
385796c8dcSSimon Schubert /* The largest amount of memory to read from the target at once. We
395796c8dcSSimon Schubert must throttle it to limit the amount of memory used by GDB during
405796c8dcSSimon Schubert generate-core-file for programs with large resident data. */
415796c8dcSSimon Schubert #define MAX_COPY_BYTES (1024 * 1024)
425796c8dcSSimon Schubert
435796c8dcSSimon Schubert static const char *default_gcore_target (void);
445796c8dcSSimon Schubert static enum bfd_architecture default_gcore_arch (void);
455796c8dcSSimon Schubert static unsigned long default_gcore_mach (void);
465796c8dcSSimon Schubert static int gcore_memory_sections (bfd *);
475796c8dcSSimon Schubert
48cf7f2e2dSJohn Marino /* create_gcore_bfd -- helper for gcore_command (exported).
49cf7f2e2dSJohn Marino Open a new bfd core file for output, and return the handle. */
505796c8dcSSimon Schubert
51cf7f2e2dSJohn Marino bfd *
create_gcore_bfd(char * filename)52cf7f2e2dSJohn Marino create_gcore_bfd (char *filename)
535796c8dcSSimon Schubert {
54*ef5ccd6cSJohn Marino bfd *obfd = gdb_bfd_openw (filename, default_gcore_target ());
555796c8dcSSimon Schubert
565796c8dcSSimon Schubert if (!obfd)
57cf7f2e2dSJohn Marino error (_("Failed to open '%s' for output."), filename);
585796c8dcSSimon Schubert bfd_set_format (obfd, bfd_core);
595796c8dcSSimon Schubert bfd_set_arch_mach (obfd, default_gcore_arch (), default_gcore_mach ());
60cf7f2e2dSJohn Marino return obfd;
61cf7f2e2dSJohn Marino }
62cf7f2e2dSJohn Marino
63cf7f2e2dSJohn Marino /* write_gcore_file -- helper for gcore_command (exported).
64cf7f2e2dSJohn Marino Compose and write the corefile data to the core file. */
65cf7f2e2dSJohn Marino
66cf7f2e2dSJohn Marino
67cf7f2e2dSJohn Marino void
write_gcore_file(bfd * obfd)68cf7f2e2dSJohn Marino write_gcore_file (bfd *obfd)
69cf7f2e2dSJohn Marino {
70cf7f2e2dSJohn Marino void *note_data = NULL;
71cf7f2e2dSJohn Marino int note_size = 0;
72cf7f2e2dSJohn Marino asection *note_sec = NULL;
735796c8dcSSimon Schubert
745796c8dcSSimon Schubert /* An external target method must build the notes section. */
75*ef5ccd6cSJohn Marino /* FIXME: uweigand/2011-10-06: All architectures that support core file
76*ef5ccd6cSJohn Marino generation should be converted to gdbarch_make_corefile_notes; at that
77*ef5ccd6cSJohn Marino point, the target vector method can be removed. */
78*ef5ccd6cSJohn Marino if (!gdbarch_make_corefile_notes_p (target_gdbarch ()))
795796c8dcSSimon Schubert note_data = target_make_corefile_notes (obfd, ¬e_size);
80*ef5ccd6cSJohn Marino else
81*ef5ccd6cSJohn Marino note_data = gdbarch_make_corefile_notes (target_gdbarch (), obfd, ¬e_size);
82*ef5ccd6cSJohn Marino
83*ef5ccd6cSJohn Marino if (note_data == NULL || note_size == 0)
84*ef5ccd6cSJohn Marino error (_("Target does not support core file generation."));
855796c8dcSSimon Schubert
865796c8dcSSimon Schubert /* Create the note section. */
875796c8dcSSimon Schubert note_sec = bfd_make_section_anyway_with_flags (obfd, "note0",
885796c8dcSSimon Schubert SEC_HAS_CONTENTS
895796c8dcSSimon Schubert | SEC_READONLY
905796c8dcSSimon Schubert | SEC_ALLOC);
915796c8dcSSimon Schubert if (note_sec == NULL)
925796c8dcSSimon Schubert error (_("Failed to create 'note' section for corefile: %s"),
935796c8dcSSimon Schubert bfd_errmsg (bfd_get_error ()));
945796c8dcSSimon Schubert
955796c8dcSSimon Schubert bfd_set_section_vma (obfd, note_sec, 0);
965796c8dcSSimon Schubert bfd_set_section_alignment (obfd, note_sec, 0);
975796c8dcSSimon Schubert bfd_set_section_size (obfd, note_sec, note_size);
985796c8dcSSimon Schubert
995796c8dcSSimon Schubert /* Now create the memory/load sections. */
1005796c8dcSSimon Schubert if (gcore_memory_sections (obfd) == 0)
1015796c8dcSSimon Schubert error (_("gcore: failed to get corefile memory sections from target."));
1025796c8dcSSimon Schubert
1035796c8dcSSimon Schubert /* Write out the contents of the note section. */
1045796c8dcSSimon Schubert if (!bfd_set_section_contents (obfd, note_sec, note_data, 0, note_size))
105*ef5ccd6cSJohn Marino warning (_("writing note section (%s)"), bfd_errmsg (bfd_get_error ()));
106cf7f2e2dSJohn Marino }
107cf7f2e2dSJohn Marino
108cf7f2e2dSJohn Marino static void
do_bfd_delete_cleanup(void * arg)109cf7f2e2dSJohn Marino do_bfd_delete_cleanup (void *arg)
110cf7f2e2dSJohn Marino {
111cf7f2e2dSJohn Marino bfd *obfd = arg;
112cf7f2e2dSJohn Marino const char *filename = obfd->filename;
113cf7f2e2dSJohn Marino
114*ef5ccd6cSJohn Marino gdb_bfd_unref (arg);
115cf7f2e2dSJohn Marino unlink (filename);
116cf7f2e2dSJohn Marino }
117cf7f2e2dSJohn Marino
118cf7f2e2dSJohn Marino /* gcore_command -- implements the 'gcore' command.
119cf7f2e2dSJohn Marino Generate a core file from the inferior process. */
120cf7f2e2dSJohn Marino
121cf7f2e2dSJohn Marino static void
gcore_command(char * args,int from_tty)122cf7f2e2dSJohn Marino gcore_command (char *args, int from_tty)
123cf7f2e2dSJohn Marino {
124cf7f2e2dSJohn Marino struct cleanup *old_chain;
125cf7f2e2dSJohn Marino char *corefilename, corefilename_buffer[40];
126cf7f2e2dSJohn Marino bfd *obfd;
127cf7f2e2dSJohn Marino
128cf7f2e2dSJohn Marino /* No use generating a corefile without a target process. */
129cf7f2e2dSJohn Marino if (!target_has_execution)
130cf7f2e2dSJohn Marino noprocess ();
131cf7f2e2dSJohn Marino
132cf7f2e2dSJohn Marino if (args && *args)
133cf7f2e2dSJohn Marino corefilename = args;
134cf7f2e2dSJohn Marino else
135cf7f2e2dSJohn Marino {
136cf7f2e2dSJohn Marino /* Default corefile name is "core.PID". */
137*ef5ccd6cSJohn Marino xsnprintf (corefilename_buffer, sizeof (corefilename_buffer),
138*ef5ccd6cSJohn Marino "core.%d", PIDGET (inferior_ptid));
139cf7f2e2dSJohn Marino corefilename = corefilename_buffer;
140cf7f2e2dSJohn Marino }
141cf7f2e2dSJohn Marino
142cf7f2e2dSJohn Marino if (info_verbose)
143cf7f2e2dSJohn Marino fprintf_filtered (gdb_stdout,
144cf7f2e2dSJohn Marino "Opening corefile '%s' for output.\n", corefilename);
145cf7f2e2dSJohn Marino
146cf7f2e2dSJohn Marino /* Open the output file. */
147cf7f2e2dSJohn Marino obfd = create_gcore_bfd (corefilename);
148cf7f2e2dSJohn Marino
149cf7f2e2dSJohn Marino /* Need a cleanup that will close and delete the file. */
150cf7f2e2dSJohn Marino old_chain = make_cleanup (do_bfd_delete_cleanup, obfd);
151cf7f2e2dSJohn Marino
152cf7f2e2dSJohn Marino /* Call worker function. */
153cf7f2e2dSJohn Marino write_gcore_file (obfd);
1545796c8dcSSimon Schubert
1555796c8dcSSimon Schubert /* Succeeded. */
1565796c8dcSSimon Schubert fprintf_filtered (gdb_stdout, "Saved corefile %s\n", corefilename);
1575796c8dcSSimon Schubert
158cf7f2e2dSJohn Marino discard_cleanups (old_chain);
159*ef5ccd6cSJohn Marino gdb_bfd_unref (obfd);
1605796c8dcSSimon Schubert }
1615796c8dcSSimon Schubert
1625796c8dcSSimon Schubert static unsigned long
default_gcore_mach(void)1635796c8dcSSimon Schubert default_gcore_mach (void)
1645796c8dcSSimon Schubert {
1655796c8dcSSimon Schubert #if 1 /* See if this even matters... */
1665796c8dcSSimon Schubert return 0;
1675796c8dcSSimon Schubert #else
1685796c8dcSSimon Schubert
169*ef5ccd6cSJohn Marino const struct bfd_arch_info *bfdarch = gdbarch_bfd_arch_info (target_gdbarch ());
1705796c8dcSSimon Schubert
1715796c8dcSSimon Schubert if (bfdarch != NULL)
1725796c8dcSSimon Schubert return bfdarch->mach;
1735796c8dcSSimon Schubert if (exec_bfd == NULL)
1745796c8dcSSimon Schubert error (_("Can't find default bfd machine type (need execfile)."));
1755796c8dcSSimon Schubert
1765796c8dcSSimon Schubert return bfd_get_mach (exec_bfd);
1775796c8dcSSimon Schubert #endif /* 1 */
1785796c8dcSSimon Schubert }
1795796c8dcSSimon Schubert
1805796c8dcSSimon Schubert static enum bfd_architecture
default_gcore_arch(void)1815796c8dcSSimon Schubert default_gcore_arch (void)
1825796c8dcSSimon Schubert {
183*ef5ccd6cSJohn Marino const struct bfd_arch_info *bfdarch = gdbarch_bfd_arch_info (target_gdbarch ());
1845796c8dcSSimon Schubert
1855796c8dcSSimon Schubert if (bfdarch != NULL)
1865796c8dcSSimon Schubert return bfdarch->arch;
1875796c8dcSSimon Schubert if (exec_bfd == NULL)
1885796c8dcSSimon Schubert error (_("Can't find bfd architecture for corefile (need execfile)."));
1895796c8dcSSimon Schubert
1905796c8dcSSimon Schubert return bfd_get_arch (exec_bfd);
1915796c8dcSSimon Schubert }
1925796c8dcSSimon Schubert
1935796c8dcSSimon Schubert static const char *
default_gcore_target(void)1945796c8dcSSimon Schubert default_gcore_target (void)
1955796c8dcSSimon Schubert {
1965796c8dcSSimon Schubert /* The gdbarch may define a target to use for core files. */
197*ef5ccd6cSJohn Marino if (gdbarch_gcore_bfd_target_p (target_gdbarch ()))
198*ef5ccd6cSJohn Marino return gdbarch_gcore_bfd_target (target_gdbarch ());
1995796c8dcSSimon Schubert
2005796c8dcSSimon Schubert /* Otherwise, try to fall back to the exec_bfd target. This will probably
2015796c8dcSSimon Schubert not work for non-ELF targets. */
2025796c8dcSSimon Schubert if (exec_bfd == NULL)
2035796c8dcSSimon Schubert return NULL;
2045796c8dcSSimon Schubert else
2055796c8dcSSimon Schubert return bfd_get_target (exec_bfd);
2065796c8dcSSimon Schubert }
2075796c8dcSSimon Schubert
2085796c8dcSSimon Schubert /* Derive a reasonable stack segment by unwinding the target stack,
2095796c8dcSSimon Schubert and store its limits in *BOTTOM and *TOP. Return non-zero if
2105796c8dcSSimon Schubert successful. */
2115796c8dcSSimon Schubert
2125796c8dcSSimon Schubert static int
derive_stack_segment(bfd_vma * bottom,bfd_vma * top)2135796c8dcSSimon Schubert derive_stack_segment (bfd_vma *bottom, bfd_vma *top)
2145796c8dcSSimon Schubert {
2155796c8dcSSimon Schubert struct frame_info *fi, *tmp_fi;
2165796c8dcSSimon Schubert
2175796c8dcSSimon Schubert gdb_assert (bottom);
2185796c8dcSSimon Schubert gdb_assert (top);
2195796c8dcSSimon Schubert
2205796c8dcSSimon Schubert /* Can't succeed without stack and registers. */
2215796c8dcSSimon Schubert if (!target_has_stack || !target_has_registers)
2225796c8dcSSimon Schubert return 0;
2235796c8dcSSimon Schubert
2245796c8dcSSimon Schubert /* Can't succeed without current frame. */
2255796c8dcSSimon Schubert fi = get_current_frame ();
2265796c8dcSSimon Schubert if (fi == NULL)
2275796c8dcSSimon Schubert return 0;
2285796c8dcSSimon Schubert
2295796c8dcSSimon Schubert /* Save frame pointer of TOS frame. */
2305796c8dcSSimon Schubert *top = get_frame_base (fi);
2315796c8dcSSimon Schubert /* If current stack pointer is more "inner", use that instead. */
2325796c8dcSSimon Schubert if (gdbarch_inner_than (get_frame_arch (fi), get_frame_sp (fi), *top))
2335796c8dcSSimon Schubert *top = get_frame_sp (fi);
2345796c8dcSSimon Schubert
2355796c8dcSSimon Schubert /* Find prev-most frame. */
2365796c8dcSSimon Schubert while ((tmp_fi = get_prev_frame (fi)) != NULL)
2375796c8dcSSimon Schubert fi = tmp_fi;
2385796c8dcSSimon Schubert
2395796c8dcSSimon Schubert /* Save frame pointer of prev-most frame. */
2405796c8dcSSimon Schubert *bottom = get_frame_base (fi);
2415796c8dcSSimon Schubert
2425796c8dcSSimon Schubert /* Now canonicalize their order, so that BOTTOM is a lower address
2435796c8dcSSimon Schubert (as opposed to a lower stack frame). */
2445796c8dcSSimon Schubert if (*bottom > *top)
2455796c8dcSSimon Schubert {
2465796c8dcSSimon Schubert bfd_vma tmp_vma;
2475796c8dcSSimon Schubert
2485796c8dcSSimon Schubert tmp_vma = *top;
2495796c8dcSSimon Schubert *top = *bottom;
2505796c8dcSSimon Schubert *bottom = tmp_vma;
2515796c8dcSSimon Schubert }
2525796c8dcSSimon Schubert
2535796c8dcSSimon Schubert return 1;
2545796c8dcSSimon Schubert }
2555796c8dcSSimon Schubert
256cf7f2e2dSJohn Marino /* call_target_sbrk --
257cf7f2e2dSJohn Marino helper function for derive_heap_segment. */
258cf7f2e2dSJohn Marino
259cf7f2e2dSJohn Marino static bfd_vma
call_target_sbrk(int sbrk_arg)260cf7f2e2dSJohn Marino call_target_sbrk (int sbrk_arg)
261cf7f2e2dSJohn Marino {
262cf7f2e2dSJohn Marino struct objfile *sbrk_objf;
263cf7f2e2dSJohn Marino struct gdbarch *gdbarch;
264cf7f2e2dSJohn Marino bfd_vma top_of_heap;
265cf7f2e2dSJohn Marino struct value *target_sbrk_arg;
266cf7f2e2dSJohn Marino struct value *sbrk_fn, *ret;
267cf7f2e2dSJohn Marino bfd_vma tmp;
268cf7f2e2dSJohn Marino
269cf7f2e2dSJohn Marino if (lookup_minimal_symbol ("sbrk", NULL, NULL) != NULL)
270cf7f2e2dSJohn Marino {
271cf7f2e2dSJohn Marino sbrk_fn = find_function_in_inferior ("sbrk", &sbrk_objf);
272cf7f2e2dSJohn Marino if (sbrk_fn == NULL)
273cf7f2e2dSJohn Marino return (bfd_vma) 0;
274cf7f2e2dSJohn Marino }
275cf7f2e2dSJohn Marino else if (lookup_minimal_symbol ("_sbrk", NULL, NULL) != NULL)
276cf7f2e2dSJohn Marino {
277cf7f2e2dSJohn Marino sbrk_fn = find_function_in_inferior ("_sbrk", &sbrk_objf);
278cf7f2e2dSJohn Marino if (sbrk_fn == NULL)
279cf7f2e2dSJohn Marino return (bfd_vma) 0;
280cf7f2e2dSJohn Marino }
281cf7f2e2dSJohn Marino else
282cf7f2e2dSJohn Marino return (bfd_vma) 0;
283cf7f2e2dSJohn Marino
284cf7f2e2dSJohn Marino gdbarch = get_objfile_arch (sbrk_objf);
285cf7f2e2dSJohn Marino target_sbrk_arg = value_from_longest (builtin_type (gdbarch)->builtin_int,
286cf7f2e2dSJohn Marino sbrk_arg);
287cf7f2e2dSJohn Marino gdb_assert (target_sbrk_arg);
288cf7f2e2dSJohn Marino ret = call_function_by_hand (sbrk_fn, 1, &target_sbrk_arg);
289cf7f2e2dSJohn Marino if (ret == NULL)
290cf7f2e2dSJohn Marino return (bfd_vma) 0;
291cf7f2e2dSJohn Marino
292cf7f2e2dSJohn Marino tmp = value_as_long (ret);
293cf7f2e2dSJohn Marino if ((LONGEST) tmp <= 0 || (LONGEST) tmp == 0xffffffff)
294cf7f2e2dSJohn Marino return (bfd_vma) 0;
295cf7f2e2dSJohn Marino
296cf7f2e2dSJohn Marino top_of_heap = tmp;
297cf7f2e2dSJohn Marino return top_of_heap;
298cf7f2e2dSJohn Marino }
299cf7f2e2dSJohn Marino
3005796c8dcSSimon Schubert /* Derive a reasonable heap segment for ABFD by looking at sbrk and
3015796c8dcSSimon Schubert the static data sections. Store its limits in *BOTTOM and *TOP.
3025796c8dcSSimon Schubert Return non-zero if successful. */
3035796c8dcSSimon Schubert
3045796c8dcSSimon Schubert static int
derive_heap_segment(bfd * abfd,bfd_vma * bottom,bfd_vma * top)3055796c8dcSSimon Schubert derive_heap_segment (bfd *abfd, bfd_vma *bottom, bfd_vma *top)
3065796c8dcSSimon Schubert {
3075796c8dcSSimon Schubert bfd_vma top_of_data_memory = 0;
3085796c8dcSSimon Schubert bfd_vma top_of_heap = 0;
3095796c8dcSSimon Schubert bfd_size_type sec_size;
3105796c8dcSSimon Schubert bfd_vma sec_vaddr;
3115796c8dcSSimon Schubert asection *sec;
3125796c8dcSSimon Schubert
3135796c8dcSSimon Schubert gdb_assert (bottom);
3145796c8dcSSimon Schubert gdb_assert (top);
3155796c8dcSSimon Schubert
3165796c8dcSSimon Schubert /* This function depends on being able to call a function in the
3175796c8dcSSimon Schubert inferior. */
3185796c8dcSSimon Schubert if (!target_has_execution)
3195796c8dcSSimon Schubert return 0;
3205796c8dcSSimon Schubert
3215796c8dcSSimon Schubert /* The following code assumes that the link map is arranged as
3225796c8dcSSimon Schubert follows (low to high addresses):
3235796c8dcSSimon Schubert
3245796c8dcSSimon Schubert ---------------------------------
3255796c8dcSSimon Schubert | text sections |
3265796c8dcSSimon Schubert ---------------------------------
3275796c8dcSSimon Schubert | data sections (including bss) |
3285796c8dcSSimon Schubert ---------------------------------
3295796c8dcSSimon Schubert | heap |
3305796c8dcSSimon Schubert --------------------------------- */
3315796c8dcSSimon Schubert
3325796c8dcSSimon Schubert for (sec = abfd->sections; sec; sec = sec->next)
3335796c8dcSSimon Schubert {
3345796c8dcSSimon Schubert if (bfd_get_section_flags (abfd, sec) & SEC_DATA
3355796c8dcSSimon Schubert || strcmp (".bss", bfd_section_name (abfd, sec)) == 0)
3365796c8dcSSimon Schubert {
3375796c8dcSSimon Schubert sec_vaddr = bfd_get_section_vma (abfd, sec);
3385796c8dcSSimon Schubert sec_size = bfd_get_section_size (sec);
3395796c8dcSSimon Schubert if (sec_vaddr + sec_size > top_of_data_memory)
3405796c8dcSSimon Schubert top_of_data_memory = sec_vaddr + sec_size;
3415796c8dcSSimon Schubert }
3425796c8dcSSimon Schubert }
3435796c8dcSSimon Schubert
344cf7f2e2dSJohn Marino top_of_heap = call_target_sbrk (0);
345cf7f2e2dSJohn Marino if (top_of_heap == (bfd_vma) 0)
3465796c8dcSSimon Schubert return 0;
3475796c8dcSSimon Schubert
3485796c8dcSSimon Schubert /* Return results. */
3495796c8dcSSimon Schubert if (top_of_heap > top_of_data_memory)
3505796c8dcSSimon Schubert {
3515796c8dcSSimon Schubert *bottom = top_of_data_memory;
3525796c8dcSSimon Schubert *top = top_of_heap;
3535796c8dcSSimon Schubert return 1;
3545796c8dcSSimon Schubert }
3555796c8dcSSimon Schubert
3565796c8dcSSimon Schubert /* No additional heap space needs to be saved. */
3575796c8dcSSimon Schubert return 0;
3585796c8dcSSimon Schubert }
3595796c8dcSSimon Schubert
3605796c8dcSSimon Schubert static void
make_output_phdrs(bfd * obfd,asection * osec,void * ignored)3615796c8dcSSimon Schubert make_output_phdrs (bfd *obfd, asection *osec, void *ignored)
3625796c8dcSSimon Schubert {
3635796c8dcSSimon Schubert int p_flags = 0;
364cf7f2e2dSJohn Marino int p_type = 0;
3655796c8dcSSimon Schubert
3665796c8dcSSimon Schubert /* FIXME: these constants may only be applicable for ELF. */
3675796c8dcSSimon Schubert if (strncmp (bfd_section_name (obfd, osec), "load", 4) == 0)
3685796c8dcSSimon Schubert p_type = PT_LOAD;
369cf7f2e2dSJohn Marino else if (strncmp (bfd_section_name (obfd, osec), "note", 4) == 0)
3705796c8dcSSimon Schubert p_type = PT_NOTE;
371cf7f2e2dSJohn Marino else
372cf7f2e2dSJohn Marino p_type = PT_NULL;
3735796c8dcSSimon Schubert
3745796c8dcSSimon Schubert p_flags |= PF_R; /* Segment is readable. */
3755796c8dcSSimon Schubert if (!(bfd_get_section_flags (obfd, osec) & SEC_READONLY))
3765796c8dcSSimon Schubert p_flags |= PF_W; /* Segment is writable. */
3775796c8dcSSimon Schubert if (bfd_get_section_flags (obfd, osec) & SEC_CODE)
3785796c8dcSSimon Schubert p_flags |= PF_X; /* Segment is executable. */
3795796c8dcSSimon Schubert
3805796c8dcSSimon Schubert bfd_record_phdr (obfd, p_type, 1, p_flags, 0, 0, 0, 0, 1, &osec);
3815796c8dcSSimon Schubert }
3825796c8dcSSimon Schubert
383*ef5ccd6cSJohn Marino /* find_memory_region_ftype implementation. DATA is 'bfd *' for the core file
384*ef5ccd6cSJohn Marino GDB is creating. */
385*ef5ccd6cSJohn Marino
3865796c8dcSSimon Schubert static int
gcore_create_callback(CORE_ADDR vaddr,unsigned long size,int read,int write,int exec,int modified,void * data)387*ef5ccd6cSJohn Marino gcore_create_callback (CORE_ADDR vaddr, unsigned long size, int read,
388*ef5ccd6cSJohn Marino int write, int exec, int modified, void *data)
3895796c8dcSSimon Schubert {
3905796c8dcSSimon Schubert bfd *obfd = data;
3915796c8dcSSimon Schubert asection *osec;
3925796c8dcSSimon Schubert flagword flags = SEC_ALLOC | SEC_HAS_CONTENTS | SEC_LOAD;
3935796c8dcSSimon Schubert
3945796c8dcSSimon Schubert /* If the memory segment has no permissions set, ignore it, otherwise
3955796c8dcSSimon Schubert when we later try to access it for read/write, we'll get an error
3965796c8dcSSimon Schubert or jam the kernel. */
397*ef5ccd6cSJohn Marino if (read == 0 && write == 0 && exec == 0 && modified == 0)
3985796c8dcSSimon Schubert {
3995796c8dcSSimon Schubert if (info_verbose)
4005796c8dcSSimon Schubert {
4015796c8dcSSimon Schubert fprintf_filtered (gdb_stdout, "Ignore segment, %s bytes at %s\n",
402*ef5ccd6cSJohn Marino plongest (size), paddress (target_gdbarch (), vaddr));
4035796c8dcSSimon Schubert }
4045796c8dcSSimon Schubert
4055796c8dcSSimon Schubert return 0;
4065796c8dcSSimon Schubert }
4075796c8dcSSimon Schubert
408*ef5ccd6cSJohn Marino if (write == 0 && modified == 0 && !solib_keep_data_in_core (vaddr, size))
4095796c8dcSSimon Schubert {
4105796c8dcSSimon Schubert /* See if this region of memory lies inside a known file on disk.
4115796c8dcSSimon Schubert If so, we can avoid copying its contents by clearing SEC_LOAD. */
4125796c8dcSSimon Schubert struct objfile *objfile;
4135796c8dcSSimon Schubert struct obj_section *objsec;
4145796c8dcSSimon Schubert
4155796c8dcSSimon Schubert ALL_OBJSECTIONS (objfile, objsec)
4165796c8dcSSimon Schubert {
4175796c8dcSSimon Schubert bfd *abfd = objfile->obfd;
4185796c8dcSSimon Schubert asection *asec = objsec->the_bfd_section;
4195796c8dcSSimon Schubert bfd_vma align = (bfd_vma) 1 << bfd_get_section_alignment (abfd,
4205796c8dcSSimon Schubert asec);
4215796c8dcSSimon Schubert bfd_vma start = obj_section_addr (objsec) & -align;
4225796c8dcSSimon Schubert bfd_vma end = (obj_section_endaddr (objsec) + align - 1) & -align;
423cf7f2e2dSJohn Marino
4245796c8dcSSimon Schubert /* Match if either the entire memory region lies inside the
4255796c8dcSSimon Schubert section (i.e. a mapping covering some pages of a large
4265796c8dcSSimon Schubert segment) or the entire section lies inside the memory region
4275796c8dcSSimon Schubert (i.e. a mapping covering multiple small sections).
4285796c8dcSSimon Schubert
4295796c8dcSSimon Schubert This BFD was synthesized from reading target memory,
4305796c8dcSSimon Schubert we don't want to omit that. */
4315796c8dcSSimon Schubert if (((vaddr >= start && vaddr + size <= end)
4325796c8dcSSimon Schubert || (start >= vaddr && end <= vaddr + size))
4335796c8dcSSimon Schubert && !(bfd_get_file_flags (abfd) & BFD_IN_MEMORY))
4345796c8dcSSimon Schubert {
435c50c785cSJohn Marino flags &= ~(SEC_LOAD | SEC_HAS_CONTENTS);
436c50c785cSJohn Marino goto keep; /* Break out of two nested for loops. */
4375796c8dcSSimon Schubert }
4385796c8dcSSimon Schubert }
4395796c8dcSSimon Schubert
440*ef5ccd6cSJohn Marino keep:;
4415796c8dcSSimon Schubert }
4425796c8dcSSimon Schubert
443*ef5ccd6cSJohn Marino if (write == 0)
444*ef5ccd6cSJohn Marino flags |= SEC_READONLY;
445*ef5ccd6cSJohn Marino
4465796c8dcSSimon Schubert if (exec)
4475796c8dcSSimon Schubert flags |= SEC_CODE;
4485796c8dcSSimon Schubert else
4495796c8dcSSimon Schubert flags |= SEC_DATA;
4505796c8dcSSimon Schubert
4515796c8dcSSimon Schubert osec = bfd_make_section_anyway_with_flags (obfd, "load", flags);
4525796c8dcSSimon Schubert if (osec == NULL)
4535796c8dcSSimon Schubert {
4545796c8dcSSimon Schubert warning (_("Couldn't make gcore segment: %s"),
4555796c8dcSSimon Schubert bfd_errmsg (bfd_get_error ()));
4565796c8dcSSimon Schubert return 1;
4575796c8dcSSimon Schubert }
4585796c8dcSSimon Schubert
4595796c8dcSSimon Schubert if (info_verbose)
4605796c8dcSSimon Schubert {
4615796c8dcSSimon Schubert fprintf_filtered (gdb_stdout, "Save segment, %s bytes at %s\n",
462*ef5ccd6cSJohn Marino plongest (size), paddress (target_gdbarch (), vaddr));
4635796c8dcSSimon Schubert }
4645796c8dcSSimon Schubert
4655796c8dcSSimon Schubert bfd_set_section_size (obfd, osec, size);
4665796c8dcSSimon Schubert bfd_set_section_vma (obfd, osec, vaddr);
4675796c8dcSSimon Schubert bfd_section_lma (obfd, osec) = 0; /* ??? bfd_set_section_lma? */
4685796c8dcSSimon Schubert return 0;
4695796c8dcSSimon Schubert }
4705796c8dcSSimon Schubert
4715796c8dcSSimon Schubert static int
objfile_find_memory_regions(find_memory_region_ftype func,void * obfd)472c50c785cSJohn Marino objfile_find_memory_regions (find_memory_region_ftype func, void *obfd)
4735796c8dcSSimon Schubert {
4745796c8dcSSimon Schubert /* Use objfile data to create memory sections. */
4755796c8dcSSimon Schubert struct objfile *objfile;
4765796c8dcSSimon Schubert struct obj_section *objsec;
4775796c8dcSSimon Schubert bfd_vma temp_bottom, temp_top;
4785796c8dcSSimon Schubert
4795796c8dcSSimon Schubert /* Call callback function for each objfile section. */
4805796c8dcSSimon Schubert ALL_OBJSECTIONS (objfile, objsec)
4815796c8dcSSimon Schubert {
4825796c8dcSSimon Schubert bfd *ibfd = objfile->obfd;
4835796c8dcSSimon Schubert asection *isec = objsec->the_bfd_section;
4845796c8dcSSimon Schubert flagword flags = bfd_get_section_flags (ibfd, isec);
4855796c8dcSSimon Schubert
486*ef5ccd6cSJohn Marino /* Separate debug info files are irrelevant for gcore. */
487*ef5ccd6cSJohn Marino if (objfile->separate_debug_objfile_backlink != NULL)
488*ef5ccd6cSJohn Marino continue;
489*ef5ccd6cSJohn Marino
4905796c8dcSSimon Schubert if ((flags & SEC_ALLOC) || (flags & SEC_LOAD))
4915796c8dcSSimon Schubert {
4925796c8dcSSimon Schubert int size = bfd_section_size (ibfd, isec);
4935796c8dcSSimon Schubert int ret;
4945796c8dcSSimon Schubert
495cf7f2e2dSJohn Marino ret = (*func) (obj_section_addr (objsec), size,
4965796c8dcSSimon Schubert 1, /* All sections will be readable. */
4975796c8dcSSimon Schubert (flags & SEC_READONLY) == 0, /* Writable. */
4985796c8dcSSimon Schubert (flags & SEC_CODE) != 0, /* Executable. */
499*ef5ccd6cSJohn Marino 1, /* MODIFIED is unknown, pass it as true. */
5005796c8dcSSimon Schubert obfd);
5015796c8dcSSimon Schubert if (ret != 0)
5025796c8dcSSimon Schubert return ret;
5035796c8dcSSimon Schubert }
5045796c8dcSSimon Schubert }
5055796c8dcSSimon Schubert
5065796c8dcSSimon Schubert /* Make a stack segment. */
5075796c8dcSSimon Schubert if (derive_stack_segment (&temp_bottom, &temp_top))
5085796c8dcSSimon Schubert (*func) (temp_bottom, temp_top - temp_bottom,
5095796c8dcSSimon Schubert 1, /* Stack section will be readable. */
5105796c8dcSSimon Schubert 1, /* Stack section will be writable. */
5115796c8dcSSimon Schubert 0, /* Stack section will not be executable. */
512*ef5ccd6cSJohn Marino 1, /* Stack section will be modified. */
5135796c8dcSSimon Schubert obfd);
5145796c8dcSSimon Schubert
5155796c8dcSSimon Schubert /* Make a heap segment. */
5165796c8dcSSimon Schubert if (derive_heap_segment (exec_bfd, &temp_bottom, &temp_top))
5175796c8dcSSimon Schubert (*func) (temp_bottom, temp_top - temp_bottom,
5185796c8dcSSimon Schubert 1, /* Heap section will be readable. */
5195796c8dcSSimon Schubert 1, /* Heap section will be writable. */
5205796c8dcSSimon Schubert 0, /* Heap section will not be executable. */
521*ef5ccd6cSJohn Marino 1, /* Heap section will be modified. */
5225796c8dcSSimon Schubert obfd);
5235796c8dcSSimon Schubert
5245796c8dcSSimon Schubert return 0;
5255796c8dcSSimon Schubert }
5265796c8dcSSimon Schubert
5275796c8dcSSimon Schubert static void
gcore_copy_callback(bfd * obfd,asection * osec,void * ignored)5285796c8dcSSimon Schubert gcore_copy_callback (bfd *obfd, asection *osec, void *ignored)
5295796c8dcSSimon Schubert {
5305796c8dcSSimon Schubert bfd_size_type size, total_size = bfd_section_size (obfd, osec);
5315796c8dcSSimon Schubert file_ptr offset = 0;
5325796c8dcSSimon Schubert struct cleanup *old_chain = NULL;
5335796c8dcSSimon Schubert void *memhunk;
5345796c8dcSSimon Schubert
5355796c8dcSSimon Schubert /* Read-only sections are marked; we don't have to copy their contents. */
5365796c8dcSSimon Schubert if ((bfd_get_section_flags (obfd, osec) & SEC_LOAD) == 0)
5375796c8dcSSimon Schubert return;
5385796c8dcSSimon Schubert
5395796c8dcSSimon Schubert /* Only interested in "load" sections. */
5405796c8dcSSimon Schubert if (strncmp ("load", bfd_section_name (obfd, osec), 4) != 0)
5415796c8dcSSimon Schubert return;
5425796c8dcSSimon Schubert
5435796c8dcSSimon Schubert size = min (total_size, MAX_COPY_BYTES);
5445796c8dcSSimon Schubert memhunk = xmalloc (size);
5455796c8dcSSimon Schubert old_chain = make_cleanup (xfree, memhunk);
5465796c8dcSSimon Schubert
5475796c8dcSSimon Schubert while (total_size > 0)
5485796c8dcSSimon Schubert {
5495796c8dcSSimon Schubert if (size > total_size)
5505796c8dcSSimon Schubert size = total_size;
5515796c8dcSSimon Schubert
5525796c8dcSSimon Schubert if (target_read_memory (bfd_section_vma (obfd, osec) + offset,
5535796c8dcSSimon Schubert memhunk, size) != 0)
5545796c8dcSSimon Schubert {
555c50c785cSJohn Marino warning (_("Memory read failed for corefile "
556c50c785cSJohn Marino "section, %s bytes at %s."),
5575796c8dcSSimon Schubert plongest (size),
558*ef5ccd6cSJohn Marino paddress (target_gdbarch (), bfd_section_vma (obfd, osec)));
5595796c8dcSSimon Schubert break;
5605796c8dcSSimon Schubert }
5615796c8dcSSimon Schubert if (!bfd_set_section_contents (obfd, osec, memhunk, offset, size))
5625796c8dcSSimon Schubert {
5635796c8dcSSimon Schubert warning (_("Failed to write corefile contents (%s)."),
5645796c8dcSSimon Schubert bfd_errmsg (bfd_get_error ()));
5655796c8dcSSimon Schubert break;
5665796c8dcSSimon Schubert }
5675796c8dcSSimon Schubert
5685796c8dcSSimon Schubert total_size -= size;
5695796c8dcSSimon Schubert offset += size;
5705796c8dcSSimon Schubert }
5715796c8dcSSimon Schubert
5725796c8dcSSimon Schubert do_cleanups (old_chain); /* Frees MEMHUNK. */
5735796c8dcSSimon Schubert }
5745796c8dcSSimon Schubert
5755796c8dcSSimon Schubert static int
gcore_memory_sections(bfd * obfd)5765796c8dcSSimon Schubert gcore_memory_sections (bfd *obfd)
5775796c8dcSSimon Schubert {
578*ef5ccd6cSJohn Marino /* Try gdbarch method first, then fall back to target method. */
579*ef5ccd6cSJohn Marino if (!gdbarch_find_memory_regions_p (target_gdbarch ())
580*ef5ccd6cSJohn Marino || gdbarch_find_memory_regions (target_gdbarch (),
581*ef5ccd6cSJohn Marino gcore_create_callback, obfd) != 0)
582*ef5ccd6cSJohn Marino {
5835796c8dcSSimon Schubert if (target_find_memory_regions (gcore_create_callback, obfd) != 0)
5845796c8dcSSimon Schubert return 0; /* FIXME: error return/msg? */
585*ef5ccd6cSJohn Marino }
5865796c8dcSSimon Schubert
5875796c8dcSSimon Schubert /* Record phdrs for section-to-segment mapping. */
5885796c8dcSSimon Schubert bfd_map_over_sections (obfd, make_output_phdrs, NULL);
5895796c8dcSSimon Schubert
5905796c8dcSSimon Schubert /* Copy memory region contents. */
5915796c8dcSSimon Schubert bfd_map_over_sections (obfd, gcore_copy_callback, NULL);
5925796c8dcSSimon Schubert
5935796c8dcSSimon Schubert return 1;
5945796c8dcSSimon Schubert }
5955796c8dcSSimon Schubert
5965796c8dcSSimon Schubert /* Provide a prototype to silence -Wmissing-prototypes. */
5975796c8dcSSimon Schubert extern initialize_file_ftype _initialize_gcore;
5985796c8dcSSimon Schubert
5995796c8dcSSimon Schubert void
_initialize_gcore(void)6005796c8dcSSimon Schubert _initialize_gcore (void)
6015796c8dcSSimon Schubert {
6025796c8dcSSimon Schubert add_com ("generate-core-file", class_files, gcore_command, _("\
6035796c8dcSSimon Schubert Save a core file with the current state of the debugged process.\n\
6045796c8dcSSimon Schubert Argument is optional filename. Default filename is 'core.<process_id>'."));
6055796c8dcSSimon Schubert
6065796c8dcSSimon Schubert add_com_alias ("gcore", "generate-core-file", class_files, 1);
6075796c8dcSSimon Schubert exec_set_find_memory_regions (objfile_find_memory_regions);
6085796c8dcSSimon Schubert }
609