Initial revision
[binutils.git] / bfd / sco5-core.c
blobf10c8f139f687f5c7ec5d219e49e203837830aec
1 /* BFD back end for SCO5 core files (U-area and raw sections)
2 Copyright 1998 Free Software Foundation, Inc.
3 Written by Jouke Numan <jnuman@hiscom.nl>
5 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "libaout.h" /* BFD a.out internal data structures */
26 #include <stdio.h>
27 #include <sys/types.h>
28 #include <sys/param.h>
29 #include <sys/dir.h>
30 #include <signal.h>
32 #include <sys/user.h> /* After a.out.h */
33 #include <sys/paccess.h>
34 #include <sys/region.h>
36 struct sco5_core_struct
38 struct user u;
41 /* forward declarations */
43 static asection *
44 make_bfd_asection PARAMS ((bfd *, const char *, flagword, bfd_size_type,
45 bfd_vma, file_ptr));
46 static asymbol *sco5_core_make_empty_symbol PARAMS ((bfd *));
47 static struct user *read_uarea PARAMS ((bfd *, int));
48 const bfd_target *sco5_core_file_p PARAMS ((bfd *abfd));
49 char *sco5_core_file_failing_command PARAMS ((bfd *abfd));
50 int sco5_core_file_failing_signal PARAMS ((bfd *abfd));
51 boolean sco5_core_file_matches_executable_p PARAMS ((bfd *core_bfd,
52 bfd *exec_bfd));
53 static void swap_abort PARAMS ((void));
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;
64 asection *asect;
66 asect = bfd_make_section_anyway (abfd, name);
67 if (!asect)
68 return NULL;
69 asect->flags = flags;
70 asect->_raw_size = _raw_size;
71 asect->vma = vma;
72 asect->filepos = filepos;
73 asect->alignment_power = 2;
75 return asect;
78 static asymbol *
79 sco5_core_make_empty_symbol (abfd)
80 bfd *abfd;
82 asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
83 if (new)
84 new->the_bfd = abfd;
85 return new;
88 static struct user *
89 read_uarea(abfd, filepos)
90 bfd *abfd;
91 int filepos;
94 struct sco5_core_struct *rawptr;
96 rawptr = ((struct sco5_core_struct *)
97 bfd_zmalloc (sizeof (struct sco5_core_struct)));
98 if (rawptr == NULL)
99 return NULL;
101 abfd->tdata.sco5_core_data = rawptr;
103 if ((bfd_seek (abfd, filepos, SEEK_SET) != 0)
104 || (bfd_read ((void *)&rawptr->u, 1, sizeof rawptr->u, abfd)
105 != sizeof rawptr->u))
107 bfd_set_error (bfd_error_wrong_format);
108 return NULL;
111 /* Sanity check perhaps??? */
112 if (rawptr->u.u_dsize > 0x1000000) /* Remember, it's in pages... */
114 bfd_set_error (bfd_error_wrong_format);
115 return NULL;
117 if (rawptr->u.u_ssize > 0x1000000)
119 bfd_set_error (bfd_error_wrong_format);
120 return NULL;
122 return &rawptr->u;
125 /* ARGSUSED */
126 const bfd_target *
127 sco5_core_file_p (abfd)
128 bfd *abfd;
130 int coffset_siz, val, nsecs, cheadoffs;
131 int coresize;
132 struct user *u;
133 struct coreoffsets coffsets;
134 struct coresecthead chead;
135 char *secname;
136 flagword flags;
138 /* Read coreoffsets region at end of core (see core(FP)) */
141 FILE *stream = bfd_cache_lookup (abfd);
142 struct stat statbuf;
143 if (stream == NULL)
144 return NULL;
145 if (fstat (fileno (stream), &statbuf) < 0)
147 bfd_set_error (bfd_error_system_call);
148 return NULL;
150 coresize = statbuf.st_size;
152 /* Last long in core is sizeof struct coreoffsets, read it */
153 if ((bfd_seek (abfd, coresize-sizeof coffset_siz, SEEK_SET) != 0)
154 || (bfd_read ((void *)&coffset_siz, 1, sizeof coffset_siz, abfd)
155 != sizeof coffset_siz) )
157 bfd_set_error (bfd_error_wrong_format);
158 return NULL;
161 /* Use it to seek start of coreoffsets region, read it and determine
162 validity */
163 if ((bfd_seek (abfd, coresize-coffset_siz, SEEK_SET) != 0)
164 || (bfd_read ((void *)&coffsets, 1, sizeof coffsets, abfd)
165 != sizeof coffsets)
166 || ((coffsets.u_info != 1) && (coffsets.u_info != C_VERSION)))
168 bfd_set_error (bfd_error_wrong_format);
169 return NULL;
173 if (coffsets.u_info == 1)
175 /* Old version, no section heads, read info from user struct */
177 u = read_uarea(abfd, coffsets.u_user);
178 if (! u)
179 return NULL;
181 if (!make_bfd_asection (abfd, ".reg", SEC_HAS_CONTENTS,
182 (bfd_size_type) coffsets.u_usize,
183 0 - (bfd_vma) u->u_ar0,
184 (file_ptr) coffsets.u_user))
185 return NULL;
187 if (!make_bfd_asection (abfd, ".data",
188 SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
189 ((bfd_size_type) u->u_exdata.ux_dsize
190 + u->u_exdata.ux_bsize),
191 (bfd_vma) u->u_exdata.ux_datorg,
192 (file_ptr) coffsets.u_data))
193 return NULL;
195 if (!make_bfd_asection (abfd, ".stack",
196 SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
197 (bfd_size_type) u->u_ssize * NBPC,
198 (bfd_vma) u->u_sub,
199 (file_ptr) coffsets.u_stack))
200 return NULL;
202 return abfd->xvec; /* Done for version 1 */
205 /* Immediately before coreoffsets region is a long with offset in core
206 to first coresecthead (CORES_OFFSETS), the long before this is the
207 number of section heads in the list. Read both longs and read the
208 coresecthead and check its validity */
210 if ((bfd_seek (abfd,
211 coresize - coffset_siz - 2 * sizeof coffset_siz,
212 SEEK_SET) != 0)
213 || (bfd_read ((void *)&nsecs, 1, sizeof nsecs, abfd) != sizeof nsecs)
214 || (bfd_read ((void *)&cheadoffs, 1, sizeof cheadoffs, abfd)
215 != sizeof cheadoffs)
216 || (bfd_seek (abfd, cheadoffs, SEEK_SET) != 0)
217 || (bfd_read ((void *)&chead, 1, sizeof chead, abfd) != sizeof chead)
218 || (chead.cs_stype != CORES_OFFSETS)
219 || (chead.cs_x.csx_magic != COREMAGIC_NUMBER))
221 bfd_set_error (bfd_error_wrong_format);
222 return NULL;
225 /* OK, we believe you. You're a core file (sure, sure). */
227 /* Now loop over all regions and map them */
228 nsecs--; /* We've seen CORES_OFFSETS already */
229 for (; nsecs; nsecs--)
231 if ((bfd_seek (abfd, chead.cs_hseek, SEEK_SET) != 0)
232 || bfd_read ((void *)&chead, 1, sizeof chead, abfd) != sizeof chead)
234 bfd_set_error (bfd_error_wrong_format);
235 return NULL;
238 switch (chead.cs_stype)
240 case CORES_MAGIC: /* Core header, check magic */
241 if (chead.cs_x.csx_magic != COREMAGIC_NUMBER)
243 bfd_set_error (bfd_error_wrong_format);
244 return NULL;
246 secname = NULL;
247 nsecs++; /* MAGIC not in section cnt!*/
248 break;
249 case CORES_UAREA: /* U-area, read in tdata */
250 u = read_uarea(abfd, chead.cs_sseek);
251 if (! u)
252 return NULL;
254 /* This is tricky. As the "register section", we give them
255 the entire upage and stack. u.u_ar0 points to where
256 "register 0" is stored. There are two tricks with this,
257 though. One is that the rest of the registers might be
258 at positive or negative (or both) displacements from
259 *u_ar0. The other is that u_ar0 is sometimes an absolute
260 address in kernel memory, and on other systems it is an
261 offset from the beginning of the `struct user'.
263 As a practical matter, we don't know where the registers
264 actually are, so we have to pass the whole area to GDB.
265 We encode the value of u_ar0 by setting the .regs section
266 up so that its virtual memory address 0 is at the place
267 pointed to by u_ar0 (by setting the vma of the start of
268 the section to -u_ar0). GDB uses this info to locate the
269 regs, using minor trickery to get around the
270 offset-or-absolute-addr problem. */
272 chead.cs_vaddr = 0 - (bfd_vma) u->u_ar0;
275 secname = ".reg";
276 flags = SEC_HAS_CONTENTS;
278 break;
279 case CORES_PREGION: /* A program region, map it */
280 switch (chead.cs_x.csx_preg.csxp_rtyp)
282 case PT_DATA:
283 secname = ".data"; /* Data region. */
284 break;
285 case PT_STACK:
286 secname = ".stack"; /* Stack region. */
287 break;
288 case PT_SHMEM:
289 secname = ".shmem"; /* Shared memory */
290 break;
291 case PT_LIBDAT:
292 secname = ".libdat"; /* Shared library data */
293 break;
294 case PT_V86:
295 secname = ".virt86"; /* Virtual 8086 mode */
296 break;
297 case PT_SHFIL:
298 secname = ".mmfile"; /* Memory mapped file */
299 break;
300 case PT_XDATA0:
301 secname = ".Xdat0"; /* XENIX data region, virtual 0 */
302 break;
303 default:
304 secname = "";
306 flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
307 break;
308 case CORES_PROC: /* struct proc */
309 case CORES_ITIMER: /* interval timers */
310 case CORES_SCOUTSNAME: /* struct scoutsname */
311 secname = NULL; /* Ignore these */
312 break;
313 default:
314 (*_bfd_error_handler) ("Unhandled SCO core file section type %d\n",
315 chead.cs_stype);
316 continue;
319 if (secname
320 && !make_bfd_asection (abfd, secname, flags,
321 (bfd_size_type) chead.cs_vsize,
322 (bfd_vma) chead.cs_vaddr,
323 (file_ptr) chead.cs_sseek))
324 return NULL;
328 return abfd->xvec;
332 char *
333 sco5_core_file_failing_command (abfd)
334 bfd *abfd;
336 char *com = abfd->tdata.sco5_core_data->u.u_comm;
337 if (*com)
338 return com;
339 else
340 return NULL;
343 /* ARGSUSED */
345 sco5_core_file_failing_signal (ignore_abfd)
346 bfd *ignore_abfd;
348 return ((ignore_abfd->tdata.sco5_core_data->u.u_sysabort != 0)
349 ? ignore_abfd->tdata.sco5_core_data->u.u_sysabort
350 : -1);
353 /* ARGSUSED */
354 boolean
355 sco5_core_file_matches_executable_p (core_bfd, exec_bfd)
356 bfd *core_bfd, *exec_bfd;
358 return true; /* FIXME, We have no way of telling at this point */
361 #define sco5_core_get_symtab_upper_bound _bfd_nosymbols_get_symtab_upper_bound
362 #define sco5_core_get_symtab _bfd_nosymbols_get_symtab
363 #define sco5_core_print_symbol _bfd_nosymbols_print_symbol
364 #define sco5_core_get_symbol_info _bfd_nosymbols_get_symbol_info
365 #define sco5_core_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name
366 #define sco5_core_get_lineno _bfd_nosymbols_get_lineno
367 #define sco5_core_find_nearest_line _bfd_nosymbols_find_nearest_line
368 #define sco5_core_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
369 #define sco5_core_read_minisymbols _bfd_nosymbols_read_minisymbols
370 #define sco5_core_minisymbol_to_symbol _bfd_nosymbols_minisymbol_to_symbol
372 /* If somebody calls any byte-swapping routines, shoot them. */
373 static void
374 swap_abort()
376 abort(); /* This way doesn't require any declaration for ANSI to fuck up */
378 #define NO_GET ((bfd_vma (*) PARAMS (( const bfd_byte *))) swap_abort )
379 #define NO_PUT ((void (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort )
380 #define NO_SIGNED_GET \
381 ((bfd_signed_vma (*) PARAMS ((const bfd_byte *))) swap_abort )
383 const bfd_target sco5_core_vec =
385 "sco5-core",
386 bfd_target_unknown_flavour,
387 BFD_ENDIAN_LITTLE, /* target byte order */
388 BFD_ENDIAN_LITTLE, /* target headers byte order */
389 (HAS_RELOC | EXEC_P | /* object flags */
390 HAS_LINENO | HAS_DEBUG |
391 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
392 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
393 0, /* symbol prefix */
394 ' ', /* ar_pad_char */
395 16, /* ar_max_namelen */
396 NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit data */
397 NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit data */
398 NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit data */
399 NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit hdrs */
400 NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit hdrs */
401 NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit hdrs */
403 { /* bfd_check_format */
404 _bfd_dummy_target, /* unknown format */
405 _bfd_dummy_target, /* object file */
406 _bfd_dummy_target, /* archive */
407 sco5_core_file_p /* a core file */
409 { /* bfd_set_format */
410 bfd_false, bfd_false,
411 bfd_false, bfd_false
413 { /* bfd_write_contents */
414 bfd_false, bfd_false,
415 bfd_false, bfd_false
418 BFD_JUMP_TABLE_GENERIC (_bfd_generic),
419 BFD_JUMP_TABLE_COPY (_bfd_generic),
420 BFD_JUMP_TABLE_CORE (sco5),
421 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
422 BFD_JUMP_TABLE_SYMBOLS (sco5_core),
423 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
424 BFD_JUMP_TABLE_WRITE (_bfd_generic),
425 BFD_JUMP_TABLE_LINK (_bfd_nolink),
426 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
428 (PTR) 0 /* backend_data */