1 /* BFD back end for Lynx core files 2 Copyright 1993 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, 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 /* ARGSUSED */ 87 const bfd_target * 88 lynx_core_file_p (abfd) 89 bfd *abfd; 90 { 91 int val; 92 int secnum; 93 struct pssentry pss; 94 size_t tcontext_size; 95 core_st_t *threadp; 96 int pagesize; 97 asection *newsect; 98 99 pagesize = getpagesize (); /* Serious cross-target issue here... This 100 really needs to come from a system-specific 101 header file. */ 102 103 /* Get the pss entry from the core file */ 104 105 if (bfd_seek (abfd, 0, SEEK_SET) != 0) 106 return NULL; 107 108 val = bfd_read ((void *)&pss, 1, sizeof pss, abfd); 109 if (val != sizeof pss) 110 { 111 /* Too small to be a core file */ 112 if (bfd_get_error () != bfd_error_system_call) 113 bfd_set_error (bfd_error_wrong_format); 114 return NULL; 115 } 116 117 core_hdr (abfd) = (struct lynx_core_struct *) 118 bfd_zalloc (abfd, sizeof (struct lynx_core_struct)); 119 120 if (!core_hdr (abfd)) 121 return NULL; 122 123 strncpy (core_command (abfd), pss.pname, PNMLEN + 1); 124 125 /* Compute the size of the thread contexts */ 126 127 tcontext_size = pss.threadcnt * sizeof (core_st_t); 128 129 /* Allocate space for the thread contexts */ 130 131 threadp = (core_st_t *)bfd_alloc (abfd, tcontext_size); 132 if (!threadp) 133 return NULL; 134 135 /* Save thread contexts */ 136 137 if (bfd_seek (abfd, pagesize, SEEK_SET) != 0) 138 return NULL; 139 140 val = bfd_read ((void *)threadp, pss.threadcnt, sizeof (core_st_t), abfd); 141 142 if (val != tcontext_size) 143 { 144 /* Probably too small to be a core file */ 145 if (bfd_get_error () != bfd_error_system_call) 146 bfd_set_error (bfd_error_wrong_format); 147 return NULL; 148 } 149 150 core_signal (abfd) = threadp->currsig; 151 152 newsect = make_bfd_asection (abfd, ".stack", 153 SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS, 154 pss.ssize, 155 pss.slimit, 156 pagesize + tcontext_size); 157 if (!newsect) 158 return NULL; 159 160 newsect = make_bfd_asection (abfd, ".data", 161 SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS, 162 pss.data_len + pss.bss_len, 163 pss.data_start, 164 pagesize + tcontext_size + pss.ssize 165 #if defined (SPARC) || defined (__SPARC__) 166 /* SPARC Lynx seems to start dumping 167 the .data section at a page 168 boundary. It's OK to check a 169 #define like SPARC here because this 170 file can only be compiled on a Lynx 171 host. */ 172 + pss.data_start % pagesize 173 #endif 174 ); 175 if (!newsect) 176 return NULL; 177 178 /* And, now for the .reg/XXX pseudo sections. Each thread has it's own 179 .reg/XXX section, where XXX is the thread id (without leading zeros). The 180 currently running thread (at the time of the core dump) also has an alias 181 called `.reg' (just to keep GDB happy). Note that we use `.reg/XXX' as 182 opposed to `.regXXX' because GDB expects that .reg2 will be the floating- 183 point registers. */ 184 185 newsect = make_bfd_asection (abfd, ".reg", 186 SEC_HAS_CONTENTS, 187 sizeof (core_st_t), 188 0, 189 pagesize); 190 if (!newsect) 191 return NULL; 192 193 for (secnum = 0; secnum < pss.threadcnt; secnum++) 194 { 195 char secname[100]; 196 197 sprintf (secname, ".reg/%d", BUILDPID (0, threadp[secnum].tid)); 198 newsect = make_bfd_asection (abfd, secname, 199 SEC_HAS_CONTENTS, 200 sizeof (core_st_t), 201 0, 202 pagesize + secnum * sizeof (core_st_t)); 203 if (!newsect) 204 return NULL; 205 } 206 207 return abfd->xvec; 208 } 209 210 char * 211 lynx_core_file_failing_command (abfd) 212 bfd *abfd; 213 { 214 return core_command (abfd); 215 } 216 217 /* ARGSUSED */ 218 int 219 lynx_core_file_failing_signal (abfd) 220 bfd *abfd; 221 { 222 return core_signal (abfd); 223 } 224 225 /* ARGSUSED */ 226 boolean 227 lynx_core_file_matches_executable_p (core_bfd, exec_bfd) 228 bfd *core_bfd, *exec_bfd; 229 { 230 return true; /* FIXME, We have no way of telling at this point */ 231 } 232 233 #endif /* LYNX_CORE */ 234