15796c8dcSSimon Schubert /* Native-dependent code for FreeBSD.
25796c8dcSSimon Schubert
3*ef5ccd6cSJohn Marino Copyright (C) 2002-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 "gdbcore.h"
225796c8dcSSimon Schubert #include "inferior.h"
235796c8dcSSimon Schubert #include "regcache.h"
245796c8dcSSimon Schubert #include "regset.h"
255796c8dcSSimon Schubert #include "gdbthread.h"
265796c8dcSSimon Schubert
275796c8dcSSimon Schubert #include "gdb_assert.h"
285796c8dcSSimon Schubert #include "gdb_string.h"
295796c8dcSSimon Schubert #include <sys/types.h>
305796c8dcSSimon Schubert #include <sys/procfs.h>
315796c8dcSSimon Schubert #include <sys/sysctl.h>
325796c8dcSSimon Schubert
335796c8dcSSimon Schubert #include "elf-bfd.h"
345796c8dcSSimon Schubert #include "fbsd-nat.h"
355796c8dcSSimon Schubert
36c50c785cSJohn Marino /* Return the name of a file that can be opened to get the symbols for
375796c8dcSSimon Schubert the child process identified by PID. */
385796c8dcSSimon Schubert
395796c8dcSSimon Schubert char *
fbsd_pid_to_exec_file(int pid)405796c8dcSSimon Schubert fbsd_pid_to_exec_file (int pid)
415796c8dcSSimon Schubert {
425796c8dcSSimon Schubert size_t len = MAXPATHLEN;
435796c8dcSSimon Schubert char *buf = xcalloc (len, sizeof (char));
445796c8dcSSimon Schubert char *path;
455796c8dcSSimon Schubert
465796c8dcSSimon Schubert #ifdef KERN_PROC_PATHNAME
475796c8dcSSimon Schubert int mib[4];
485796c8dcSSimon Schubert
495796c8dcSSimon Schubert mib[0] = CTL_KERN;
505796c8dcSSimon Schubert mib[1] = KERN_PROC;
515796c8dcSSimon Schubert mib[2] = KERN_PROC_PATHNAME;
525796c8dcSSimon Schubert mib[3] = pid;
535796c8dcSSimon Schubert if (sysctl (mib, 4, buf, &len, NULL, 0) == 0)
545796c8dcSSimon Schubert return buf;
555796c8dcSSimon Schubert #endif
565796c8dcSSimon Schubert
575796c8dcSSimon Schubert path = xstrprintf ("/proc/%d/file", pid);
58*ef5ccd6cSJohn Marino if (readlink (path, buf, MAXPATHLEN - 1) == -1)
595796c8dcSSimon Schubert {
605796c8dcSSimon Schubert xfree (buf);
615796c8dcSSimon Schubert buf = NULL;
625796c8dcSSimon Schubert }
635796c8dcSSimon Schubert
645796c8dcSSimon Schubert xfree (path);
655796c8dcSSimon Schubert return buf;
665796c8dcSSimon Schubert }
675796c8dcSSimon Schubert
685796c8dcSSimon Schubert static int
fbsd_read_mapping(FILE * mapfile,unsigned long * start,unsigned long * end,char * protection)695796c8dcSSimon Schubert fbsd_read_mapping (FILE *mapfile, unsigned long *start, unsigned long *end,
705796c8dcSSimon Schubert char *protection)
715796c8dcSSimon Schubert {
725796c8dcSSimon Schubert /* FreeBSD 5.1-RELEASE uses a 256-byte buffer. */
735796c8dcSSimon Schubert char buf[256];
745796c8dcSSimon Schubert int resident, privateresident;
755796c8dcSSimon Schubert unsigned long obj;
765796c8dcSSimon Schubert int ret = EOF;
775796c8dcSSimon Schubert
785796c8dcSSimon Schubert /* As of FreeBSD 5.0-RELEASE, the layout is described in
795796c8dcSSimon Schubert /usr/src/sys/fs/procfs/procfs_map.c. Somewhere in 5.1-CURRENT a
805796c8dcSSimon Schubert new column was added to the procfs map. Therefore we can't use
815796c8dcSSimon Schubert fscanf since we need to support older releases too. */
825796c8dcSSimon Schubert if (fgets (buf, sizeof buf, mapfile) != NULL)
835796c8dcSSimon Schubert ret = sscanf (buf, "%lx %lx %d %d %lx %s", start, end,
845796c8dcSSimon Schubert &resident, &privateresident, &obj, protection);
855796c8dcSSimon Schubert
865796c8dcSSimon Schubert return (ret != 0 && ret != EOF);
875796c8dcSSimon Schubert }
885796c8dcSSimon Schubert
895796c8dcSSimon Schubert /* Iterate over all the memory regions in the current inferior,
905796c8dcSSimon Schubert calling FUNC for each memory region. OBFD is passed as the last
915796c8dcSSimon Schubert argument to FUNC. */
925796c8dcSSimon Schubert
935796c8dcSSimon Schubert int
fbsd_find_memory_regions(find_memory_region_ftype func,void * obfd)94c50c785cSJohn Marino fbsd_find_memory_regions (find_memory_region_ftype func, void *obfd)
955796c8dcSSimon Schubert {
965796c8dcSSimon Schubert pid_t pid = ptid_get_pid (inferior_ptid);
975796c8dcSSimon Schubert char *mapfilename;
985796c8dcSSimon Schubert FILE *mapfile;
995796c8dcSSimon Schubert unsigned long start, end, size;
1005796c8dcSSimon Schubert char protection[4];
1015796c8dcSSimon Schubert int read, write, exec;
1025796c8dcSSimon Schubert struct cleanup *cleanup;
1035796c8dcSSimon Schubert
1045796c8dcSSimon Schubert mapfilename = xstrprintf ("/proc/%ld/map", (long) pid);
1055796c8dcSSimon Schubert cleanup = make_cleanup (xfree, mapfilename);
1065796c8dcSSimon Schubert mapfile = fopen (mapfilename, "r");
1075796c8dcSSimon Schubert if (mapfile == NULL)
1085796c8dcSSimon Schubert error (_("Couldn't open %s."), mapfilename);
1095796c8dcSSimon Schubert make_cleanup_fclose (mapfile);
1105796c8dcSSimon Schubert
1115796c8dcSSimon Schubert if (info_verbose)
1125796c8dcSSimon Schubert fprintf_filtered (gdb_stdout,
1135796c8dcSSimon Schubert "Reading memory regions from %s\n", mapfilename);
1145796c8dcSSimon Schubert
1155796c8dcSSimon Schubert /* Now iterate until end-of-file. */
1165796c8dcSSimon Schubert while (fbsd_read_mapping (mapfile, &start, &end, &protection[0]))
1175796c8dcSSimon Schubert {
1185796c8dcSSimon Schubert size = end - start;
1195796c8dcSSimon Schubert
1205796c8dcSSimon Schubert read = (strchr (protection, 'r') != 0);
1215796c8dcSSimon Schubert write = (strchr (protection, 'w') != 0);
1225796c8dcSSimon Schubert exec = (strchr (protection, 'x') != 0);
1235796c8dcSSimon Schubert
1245796c8dcSSimon Schubert if (info_verbose)
1255796c8dcSSimon Schubert {
1265796c8dcSSimon Schubert fprintf_filtered (gdb_stdout,
1275796c8dcSSimon Schubert "Save segment, %ld bytes at %s (%c%c%c)\n",
128*ef5ccd6cSJohn Marino size, paddress (target_gdbarch (), start),
1295796c8dcSSimon Schubert read ? 'r' : '-',
1305796c8dcSSimon Schubert write ? 'w' : '-',
1315796c8dcSSimon Schubert exec ? 'x' : '-');
1325796c8dcSSimon Schubert }
1335796c8dcSSimon Schubert
134*ef5ccd6cSJohn Marino /* Invoke the callback function to create the corefile segment.
135*ef5ccd6cSJohn Marino Pass MODIFIED as true, we do not know the real modification state. */
136*ef5ccd6cSJohn Marino func (start, size, read, write, exec, 1, obfd);
1375796c8dcSSimon Schubert }
1385796c8dcSSimon Schubert
1395796c8dcSSimon Schubert do_cleanups (cleanup);
1405796c8dcSSimon Schubert return 0;
1415796c8dcSSimon Schubert }
1425796c8dcSSimon Schubert
1435796c8dcSSimon Schubert static int
find_signalled_thread(struct thread_info * info,void * data)1445796c8dcSSimon Schubert find_signalled_thread (struct thread_info *info, void *data)
1455796c8dcSSimon Schubert {
146*ef5ccd6cSJohn Marino if (info->suspend.stop_signal != GDB_SIGNAL_0
1475796c8dcSSimon Schubert && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid))
1485796c8dcSSimon Schubert return 1;
1495796c8dcSSimon Schubert
1505796c8dcSSimon Schubert return 0;
1515796c8dcSSimon Schubert }
1525796c8dcSSimon Schubert
153*ef5ccd6cSJohn Marino static enum gdb_signal
find_stop_signal(void)1545796c8dcSSimon Schubert find_stop_signal (void)
1555796c8dcSSimon Schubert {
1565796c8dcSSimon Schubert struct thread_info *info =
1575796c8dcSSimon Schubert iterate_over_threads (find_signalled_thread, NULL);
1585796c8dcSSimon Schubert
1595796c8dcSSimon Schubert if (info)
160c50c785cSJohn Marino return info->suspend.stop_signal;
1615796c8dcSSimon Schubert else
162*ef5ccd6cSJohn Marino return GDB_SIGNAL_0;
1635796c8dcSSimon Schubert }
1645796c8dcSSimon Schubert
1655796c8dcSSimon Schubert /* Create appropriate note sections for a corefile, returning them in
1665796c8dcSSimon Schubert allocated memory. */
1675796c8dcSSimon Schubert
1685796c8dcSSimon Schubert char *
fbsd_make_corefile_notes(bfd * obfd,int * note_size)1695796c8dcSSimon Schubert fbsd_make_corefile_notes (bfd *obfd, int *note_size)
1705796c8dcSSimon Schubert {
1715796c8dcSSimon Schubert const struct regcache *regcache = get_current_regcache ();
1725796c8dcSSimon Schubert struct gdbarch *gdbarch = get_regcache_arch (regcache);
1735796c8dcSSimon Schubert gregset_t gregs;
1745796c8dcSSimon Schubert fpregset_t fpregs;
1755796c8dcSSimon Schubert char *note_data = NULL;
1765796c8dcSSimon Schubert Elf_Internal_Ehdr *i_ehdrp;
1775796c8dcSSimon Schubert const struct regset *regset;
1785796c8dcSSimon Schubert size_t size;
1795796c8dcSSimon Schubert
1805796c8dcSSimon Schubert /* Put a "FreeBSD" label in the ELF header. */
1815796c8dcSSimon Schubert i_ehdrp = elf_elfheader (obfd);
1825796c8dcSSimon Schubert i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
1835796c8dcSSimon Schubert
1845796c8dcSSimon Schubert gdb_assert (gdbarch_regset_from_core_section_p (gdbarch));
1855796c8dcSSimon Schubert
1865796c8dcSSimon Schubert size = sizeof gregs;
1875796c8dcSSimon Schubert regset = gdbarch_regset_from_core_section (gdbarch, ".reg", size);
1885796c8dcSSimon Schubert gdb_assert (regset && regset->collect_regset);
1895796c8dcSSimon Schubert regset->collect_regset (regset, regcache, -1, &gregs, size);
1905796c8dcSSimon Schubert
1915796c8dcSSimon Schubert note_data = elfcore_write_prstatus (obfd, note_data, note_size,
1925796c8dcSSimon Schubert ptid_get_pid (inferior_ptid),
1935796c8dcSSimon Schubert find_stop_signal (), &gregs);
1945796c8dcSSimon Schubert
1955796c8dcSSimon Schubert size = sizeof fpregs;
1965796c8dcSSimon Schubert regset = gdbarch_regset_from_core_section (gdbarch, ".reg2", size);
1975796c8dcSSimon Schubert gdb_assert (regset && regset->collect_regset);
1985796c8dcSSimon Schubert regset->collect_regset (regset, regcache, -1, &fpregs, size);
1995796c8dcSSimon Schubert
2005796c8dcSSimon Schubert note_data = elfcore_write_prfpreg (obfd, note_data, note_size,
2015796c8dcSSimon Schubert &fpregs, sizeof (fpregs));
2025796c8dcSSimon Schubert
2035796c8dcSSimon Schubert if (get_exec_file (0))
2045796c8dcSSimon Schubert {
205c50c785cSJohn Marino const char *fname = lbasename (get_exec_file (0));
2065796c8dcSSimon Schubert char *psargs = xstrdup (fname);
2075796c8dcSSimon Schubert
2085796c8dcSSimon Schubert if (get_inferior_args ())
209cf7f2e2dSJohn Marino psargs = reconcat (psargs, psargs, " ", get_inferior_args (),
210cf7f2e2dSJohn Marino (char *) NULL);
2115796c8dcSSimon Schubert
2125796c8dcSSimon Schubert note_data = elfcore_write_prpsinfo (obfd, note_data, note_size,
2135796c8dcSSimon Schubert fname, psargs);
2145796c8dcSSimon Schubert }
2155796c8dcSSimon Schubert
2165796c8dcSSimon Schubert make_cleanup (xfree, note_data);
2175796c8dcSSimon Schubert return note_data;
2185796c8dcSSimon Schubert }
219