1130803Smarcel/* FreeBSD-specific methods for using the /proc file system. 2130803Smarcel 3130803Smarcel Copyright 2002, 2003 Free Software Foundation, Inc. 4130803Smarcel 5130803Smarcel This file is part of GDB. 6130803Smarcel 7130803Smarcel This program is free software; you can redistribute it and/or modify 8130803Smarcel it under the terms of the GNU General Public License as published by 9130803Smarcel the Free Software Foundation; either version 2 of the License, or 10130803Smarcel (at your option) any later version. 11130803Smarcel 12130803Smarcel This program is distributed in the hope that it will be useful, 13130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 14130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15130803Smarcel GNU General Public License for more details. 16130803Smarcel 17130803Smarcel You should have received a copy of the GNU General Public License 18130803Smarcel along with this program; if not, write to the Free Software 19130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 20130803Smarcel Boston, MA 02111-1307, USA. */ 21130803Smarcel 22130803Smarcel#include "defs.h" 23130803Smarcel#include "gdbcore.h" 24130803Smarcel#include "inferior.h" 25130803Smarcel#include "gdb_string.h" 26130803Smarcel 27130803Smarcel#include <sys/procfs.h> 28130803Smarcel#include <sys/types.h> 29130803Smarcel 30130803Smarcel#include "elf-bfd.h" 31130803Smarcel 32130803Smarcel#include "gregset.h" 33130803Smarcel 34130803Smarcelchar * 35130803Smarcelchild_pid_to_exec_file (int pid) 36130803Smarcel{ 37130803Smarcel char *path; 38130803Smarcel char *buf; 39130803Smarcel 40130803Smarcel xasprintf (&path, "/proc/%d/file", pid); 41130803Smarcel buf = xcalloc (MAXPATHLEN, sizeof (char)); 42130803Smarcel make_cleanup (xfree, path); 43130803Smarcel make_cleanup (xfree, buf); 44130803Smarcel 45130803Smarcel if (readlink (path, buf, MAXPATHLEN) > 0) 46130803Smarcel return buf; 47130803Smarcel 48130803Smarcel return NULL; 49130803Smarcel} 50130803Smarcel 51130803Smarcelstatic int 52130803Smarcelread_mapping (FILE *mapfile, unsigned long *start, unsigned long *end, 53130803Smarcel char *protection) 54130803Smarcel{ 55130803Smarcel /* FreeBSD 5.1-RELEASE uses a 256-byte buffer. */ 56130803Smarcel char buf[256]; 57130803Smarcel int resident, privateresident; 58130803Smarcel unsigned long obj; 59130803Smarcel int ret = EOF; 60130803Smarcel 61130803Smarcel /* As of FreeBSD 5.0-RELEASE, the layout is described in 62130803Smarcel /usr/src/sys/fs/procfs/procfs_map.c. Somewhere in 5.1-CURRENT a 63130803Smarcel new column was added to the procfs map. Therefore we can't use 64130803Smarcel fscanf since we need to support older releases too. */ 65130803Smarcel if (fgets (buf, sizeof buf, mapfile) != NULL) 66130803Smarcel ret = sscanf (buf, "%lx %lx %d %d %lx %s", start, end, 67130803Smarcel &resident, &privateresident, &obj, protection); 68130803Smarcel 69130803Smarcel return (ret != 0 && ret != EOF); 70130803Smarcel} 71130803Smarcel 72130803Smarcelstatic int 73130803Smarcelfbsd_find_memory_regions (int (*func) (CORE_ADDR, unsigned long, 74130803Smarcel int, int, int, void *), 75130803Smarcel void *obfd) 76130803Smarcel{ 77130803Smarcel pid_t pid = ptid_get_pid (inferior_ptid); 78130803Smarcel char *mapfilename; 79130803Smarcel FILE *mapfile; 80130803Smarcel unsigned long start, end, size; 81130803Smarcel char protection[4]; 82130803Smarcel int read, write, exec; 83130803Smarcel 84130803Smarcel xasprintf (&mapfilename, "/proc/%ld/map", (long) pid); 85130803Smarcel mapfile = fopen (mapfilename, "r"); 86130803Smarcel if (mapfile == NULL) 87130803Smarcel error ("Couldn't open %s\n", mapfilename); 88130803Smarcel 89130803Smarcel if (info_verbose) 90130803Smarcel fprintf_filtered (gdb_stdout, 91130803Smarcel "Reading memory regions from %s\n", mapfilename); 92130803Smarcel 93130803Smarcel /* Now iterate until end-of-file. */ 94130803Smarcel while (read_mapping (mapfile, &start, &end, &protection[0])) 95130803Smarcel { 96130803Smarcel size = end - start; 97130803Smarcel 98130803Smarcel read = (strchr (protection, 'r') != 0); 99130803Smarcel write = (strchr (protection, 'w') != 0); 100130803Smarcel exec = (strchr (protection, 'x') != 0); 101130803Smarcel 102130803Smarcel if (info_verbose) 103130803Smarcel { 104130803Smarcel fprintf_filtered (gdb_stdout, 105130803Smarcel "Save segment, %ld bytes at 0x%s (%c%c%c)\n", 106130803Smarcel size, paddr_nz (start), 107130803Smarcel read ? 'r' : '-', 108130803Smarcel write ? 'w' : '-', 109130803Smarcel exec ? 'x' : '-'); 110130803Smarcel } 111130803Smarcel 112130803Smarcel /* Invoke the callback function to create the corefile segment. */ 113130803Smarcel func (start, size, read, write, exec, obfd); 114130803Smarcel } 115130803Smarcel 116130803Smarcel fclose (mapfile); 117130803Smarcel return 0; 118130803Smarcel} 119130803Smarcel 120130803Smarcelstatic char * 121130803Smarcelfbsd_make_corefile_notes (bfd *obfd, int *note_size) 122130803Smarcel{ 123130803Smarcel gregset_t gregs; 124130803Smarcel fpregset_t fpregs; 125130803Smarcel char *note_data = NULL; 126130803Smarcel Elf_Internal_Ehdr *i_ehdrp; 127215679Sattilio char fakename; 128130803Smarcel 129130803Smarcel /* Put a "FreeBSD" label in the ELF header. */ 130130803Smarcel i_ehdrp = elf_elfheader (obfd); 131130803Smarcel i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; 132130803Smarcel 133130803Smarcel fill_gregset (&gregs, -1); 134130803Smarcel note_data = elfcore_write_prstatus (obfd, note_data, note_size, 135130803Smarcel ptid_get_pid (inferior_ptid), 136130803Smarcel stop_signal, &gregs); 137130803Smarcel 138130803Smarcel fill_fpregset (&fpregs, -1); 139130803Smarcel note_data = elfcore_write_prfpreg (obfd, note_data, note_size, 140130803Smarcel &fpregs, sizeof (fpregs)); 141130803Smarcel 142215679Sattilio fakename = '\0'; 143215679Sattilio note_data = elfcore_write_thrmisc (obfd, note_data, note_size, 144215679Sattilio &fakename, sizeof (fakename)); 145215679Sattilio 146130803Smarcel if (get_exec_file (0)) 147130803Smarcel { 148130803Smarcel char *fname = strrchr (get_exec_file (0), '/') + 1; 149130803Smarcel char *psargs = xstrdup (fname); 150130803Smarcel 151130803Smarcel if (get_inferior_args ()) 152130803Smarcel psargs = reconcat (psargs, psargs, " ", get_inferior_args (), NULL); 153130803Smarcel 154130803Smarcel note_data = elfcore_write_prpsinfo (obfd, note_data, note_size, 155130803Smarcel fname, psargs); 156130803Smarcel } 157130803Smarcel 158130803Smarcel make_cleanup (xfree, note_data); 159130803Smarcel return note_data; 160130803Smarcel} 161130803Smarcel 162130803Smarcel 163130803Smarcelvoid 164130803Smarcel_initialize_fbsd_proc (void) 165130803Smarcel{ 166130803Smarcel extern void inftarg_set_find_memory_regions (); 167130803Smarcel extern void inftarg_set_make_corefile_notes (); 168130803Smarcel 169130803Smarcel inftarg_set_find_memory_regions (fbsd_find_memory_regions); 170130803Smarcel inftarg_set_make_corefile_notes (fbsd_make_corefile_notes); 171130803Smarcel} 172