1/* FreeBSD-specific methods for using the /proc file system. 2 3 Copyright 2002, 2003 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 59 Temple Place - Suite 330, 20 Boston, MA 02111-1307, USA. */ 21 22#include "defs.h" 23#include "gdbcore.h" 24#include "inferior.h" 25#include "gdb_string.h" 26 27#include <sys/procfs.h> 28#include <sys/types.h> 29 30#include "elf-bfd.h" 31 32#include "gregset.h" 33 34char * 35child_pid_to_exec_file (int pid) 36{ 37 char *path; 38 char *buf; 39 40 xasprintf (&path, "/proc/%d/file", pid); 41 buf = xcalloc (MAXPATHLEN, sizeof (char)); 42 make_cleanup (xfree, path); 43 make_cleanup (xfree, buf); 44 45 if (readlink (path, buf, MAXPATHLEN) > 0) 46 return buf; 47 48 return NULL; 49} 50 51static int 52read_mapping (FILE *mapfile, unsigned long *start, unsigned long *end, 53 char *protection) 54{ 55 /* FreeBSD 5.1-RELEASE uses a 256-byte buffer. */ 56 char buf[256]; 57 int resident, privateresident; 58 unsigned long obj; 59 int ret = EOF; 60 61 /* As of FreeBSD 5.0-RELEASE, the layout is described in 62 /usr/src/sys/fs/procfs/procfs_map.c. Somewhere in 5.1-CURRENT a 63 new column was added to the procfs map. Therefore we can't use 64 fscanf since we need to support older releases too. */ 65 if (fgets (buf, sizeof buf, mapfile) != NULL) 66 ret = sscanf (buf, "%lx %lx %d %d %lx %s", start, end, 67 &resident, &privateresident, &obj, protection); 68 69 return (ret != 0 && ret != EOF); 70} 71 72static int 73fbsd_find_memory_regions (int (*func) (CORE_ADDR, unsigned long, 74 int, int, int, void *), 75 void *obfd) 76{ 77 pid_t pid = ptid_get_pid (inferior_ptid); 78 char *mapfilename; 79 FILE *mapfile; 80 unsigned long start, end, size; 81 char protection[4]; 82 int read, write, exec; 83 84 xasprintf (&mapfilename, "/proc/%ld/map", (long) pid); 85 mapfile = fopen (mapfilename, "r"); 86 if (mapfile == NULL) 87 error ("Couldn't open %s\n", mapfilename); 88 89 if (info_verbose) 90 fprintf_filtered (gdb_stdout, 91 "Reading memory regions from %s\n", mapfilename); 92 93 /* Now iterate until end-of-file. */ 94 while (read_mapping (mapfile, &start, &end, &protection[0])) 95 { 96 size = end - start; 97 98 read = (strchr (protection, 'r') != 0); 99 write = (strchr (protection, 'w') != 0); 100 exec = (strchr (protection, 'x') != 0); 101 102 if (info_verbose) 103 { 104 fprintf_filtered (gdb_stdout, 105 "Save segment, %ld bytes at 0x%s (%c%c%c)\n", 106 size, paddr_nz (start), 107 read ? 'r' : '-', 108 write ? 'w' : '-', 109 exec ? 'x' : '-'); 110 } 111 112 /* Invoke the callback function to create the corefile segment. */ 113 func (start, size, read, write, exec, obfd); 114 } 115 116 fclose (mapfile); 117 return 0; 118} 119 120static char * 121fbsd_make_corefile_notes (bfd *obfd, int *note_size) 122{ 123 gregset_t gregs; 124 fpregset_t fpregs; 125 char *note_data = NULL; 126 Elf_Internal_Ehdr *i_ehdrp; 127 char fakename; 128 129 /* Put a "FreeBSD" label in the ELF header. */ 130 i_ehdrp = elf_elfheader (obfd); 131 i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; 132 133 fill_gregset (&gregs, -1); 134 note_data = elfcore_write_prstatus (obfd, note_data, note_size, 135 ptid_get_pid (inferior_ptid), 136 stop_signal, &gregs); 137 138 fill_fpregset (&fpregs, -1); 139 note_data = elfcore_write_prfpreg (obfd, note_data, note_size, 140 &fpregs, sizeof (fpregs)); 141 142 fakename = '\0'; 143 note_data = elfcore_write_thrmisc (obfd, note_data, note_size, 144 &fakename, sizeof (fakename)); 145 146 if (get_exec_file (0)) 147 { 148 char *fname = strrchr (get_exec_file (0), '/') + 1; 149 char *psargs = xstrdup (fname); 150 151 if (get_inferior_args ()) 152 psargs = reconcat (psargs, psargs, " ", get_inferior_args (), NULL); 153 154 note_data = elfcore_write_prpsinfo (obfd, note_data, note_size, 155 fname, psargs); 156 } 157 158 make_cleanup (xfree, note_data); 159 return note_data; 160} 161 162 163void 164_initialize_fbsd_proc (void) 165{ 166 extern void inftarg_set_find_memory_regions (); 167 extern void inftarg_set_make_corefile_notes (); 168 169 inftarg_set_find_memory_regions (fbsd_find_memory_regions); 170 inftarg_set_make_corefile_notes (fbsd_make_corefile_notes); 171} 172