1 /* BFD back end for Lynx core files 2 Copyright 1993, 1994, 1995, 2001, 2002 Free Software Foundation, Inc. 3 Written by Stu Grossman of Cygnus Support. 4 5 This file is part of BFD, the Binary File Descriptor library. 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, Boston, MA 02111-1307, USA. */ 20 21 #include "bfd.h" 22 #include "sysdep.h" 23 #include "libbfd.h" 24 25 #ifdef LYNX_CORE 26 27 #include <sys/conf.h> 28 #include <sys/kernel.h> 29 /* sys/kernel.h should define this, but doesn't always, sigh. */ 30 #ifndef __LYNXOS 31 #define __LYNXOS 32 #endif 33 #include <sys/mem.h> 34 #include <sys/signal.h> 35 #include <sys/time.h> 36 #include <sys/resource.h> 37 #include <sys/itimer.h> 38 #include <sys/file.h> 39 #include <sys/proc.h> 40 41 /* These are stored in the bfd's tdata */ 42 43 struct lynx_core_struct 44 { 45 int sig; 46 char cmd[PNMLEN + 1]; 47 }; 48 49 #define core_hdr(bfd) ((bfd)->tdata.lynx_core_data) 50 #define core_signal(bfd) (core_hdr(bfd)->sig) 51 #define core_command(bfd) (core_hdr(bfd)->cmd) 52 53 /* Handle Lynx core dump file. */ 54 55 static asection * 56 make_bfd_asection (abfd, name, flags, _raw_size, vma, filepos) 57 bfd *abfd; 58 const char *name; 59 flagword flags; 60 bfd_size_type _raw_size; 61 bfd_vma vma; 62 file_ptr filepos; 63 { 64 asection *asect; 65 char *newname; 66 67 newname = bfd_alloc (abfd, (bfd_size_type) strlen (name) + 1); 68 if (!newname) 69 return NULL; 70 71 strcpy (newname, name); 72 73 asect = bfd_make_section (abfd, newname); 74 if (!asect) 75 return NULL; 76 77 asect->flags = flags; 78 asect->_raw_size = _raw_size; 79 asect->vma = vma; 80 asect->filepos = filepos; 81 asect->alignment_power = 2; 82 83 return asect; 84 } 85 86 const bfd_target * 87 lynx_core_file_p (abfd) 88 bfd *abfd; 89 { 90 int secnum; 91 struct pssentry pss; 92 bfd_size_type tcontext_size; 93 core_st_t *threadp; 94 int pagesize; 95 asection *newsect; 96 bfd_size_type amt; 97 98 pagesize = getpagesize (); /* Serious cross-target issue here... This 99 really needs to come from a system-specific 100 header file. */ 101 102 /* Get the pss entry from the core file */ 103 104 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) 105 return NULL; 106 107 amt = sizeof pss; 108 if (bfd_bread ((void *) &pss, amt, abfd) != amt) 109 { 110 /* Too small to be a core file */ 111 if (bfd_get_error () != bfd_error_system_call) 112 bfd_set_error (bfd_error_wrong_format); 113 return NULL; 114 } 115 116 amt = sizeof (struct lynx_core_struct); 117 core_hdr (abfd) = (struct lynx_core_struct *) bfd_zalloc (abfd, amt); 118 119 if (!core_hdr (abfd)) 120 return NULL; 121 122 strncpy (core_command (abfd), pss.pname, PNMLEN + 1); 123 124 /* Compute the size of the thread contexts */ 125 126 tcontext_size = pss.threadcnt * sizeof (core_st_t); 127 128 /* Allocate space for the thread contexts */ 129 130 threadp = (core_st_t *) bfd_alloc (abfd, tcontext_size); 131 if (!threadp) 132 goto fail; 133 134 /* Save thread contexts */ 135 136 if (bfd_seek (abfd, (file_ptr) pagesize, SEEK_SET) != 0) 137 goto fail; 138 139 if (bfd_bread ((void *) threadp, tcontext_size, abfd) != tcontext_size) 140 { 141 /* Probably too small to be a core file */ 142 if (bfd_get_error () != bfd_error_system_call) 143 bfd_set_error (bfd_error_wrong_format); 144 goto fail; 145 } 146 147 core_signal (abfd) = threadp->currsig; 148 149 newsect = make_bfd_asection (abfd, ".stack", 150 SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS, 151 pss.ssize, 152 pss.slimit, 153 pagesize + tcontext_size); 154 if (!newsect) 155 goto fail; 156 157 newsect = make_bfd_asection (abfd, ".data", 158 SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS, 159 pss.data_len + pss.bss_len, 160 pss.data_start, 161 pagesize + tcontext_size + pss.ssize 162 #if defined (SPARC) || defined (__SPARC__) 163 /* SPARC Lynx seems to start dumping 164 the .data section at a page 165 boundary. It's OK to check a 166 #define like SPARC here because this 167 file can only be compiled on a Lynx 168 host. */ 169 + pss.data_start % pagesize 170 #endif 171 ); 172 if (!newsect) 173 goto fail; 174 175 /* And, now for the .reg/XXX pseudo sections. Each thread has it's own 176 .reg/XXX section, where XXX is the thread id (without leading zeros). The 177 currently running thread (at the time of the core dump) also has an alias 178 called `.reg' (just to keep GDB happy). Note that we use `.reg/XXX' as 179 opposed to `.regXXX' because GDB expects that .reg2 will be the floating- 180 point registers. */ 181 182 newsect = make_bfd_asection (abfd, ".reg", 183 SEC_HAS_CONTENTS, 184 sizeof (core_st_t), 185 0, 186 pagesize); 187 if (!newsect) 188 goto fail; 189 190 for (secnum = 0; secnum < pss.threadcnt; secnum++) 191 { 192 char secname[100]; 193 194 sprintf (secname, ".reg/%d", BUILDPID (0, threadp[secnum].tid)); 195 newsect = make_bfd_asection (abfd, secname, 196 SEC_HAS_CONTENTS, 197 sizeof (core_st_t), 198 0, 199 pagesize + secnum * sizeof (core_st_t)); 200 if (!newsect) 201 goto fail; 202 } 203 204 return abfd->xvec; 205 206 fail: 207 bfd_release (abfd, core_hdr (abfd)); 208 core_hdr (abfd) = NULL; 209 bfd_section_list_clear (abfd); 210 return NULL; 211 } 212 213 char * 214 lynx_core_file_failing_command (abfd) 215 bfd *abfd; 216 { 217 return core_command (abfd); 218 } 219 220 int 221 lynx_core_file_failing_signal (abfd) 222 bfd *abfd; 223 { 224 return core_signal (abfd); 225 } 226 227 bfd_boolean 228 lynx_core_file_matches_executable_p (core_bfd, exec_bfd) 229 bfd *core_bfd, *exec_bfd; 230 { 231 return TRUE; /* FIXME, We have no way of telling at this point */ 232 } 233 234 #endif /* LYNX_CORE */ 235