* cc-with-index.sh: Fix typos in comment.
[deliverable/binutils-gdb.git] / bfd / sco5-core.c
CommitLineData
252b5132 1/* BFD back end for SCO5 core files (U-area and raw sections)
3db64b00 2 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
edeb6e24 3 Free Software Foundation, Inc.
252b5132
RH
4 Written by Jouke Numan <jnuman@hiscom.nl>
5
cd123cb7
NC
6 This file is part of BFD, the Binary File Descriptor library.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
252b5132 22
252b5132 23#include "sysdep.h"
3db64b00 24#include "bfd.h"
252b5132 25#include "libbfd.h"
b34976b6 26#include "libaout.h" /* BFD a.out internal data structures */
252b5132
RH
27
28#include <stdio.h>
29#include <sys/types.h>
30#include <sys/param.h>
31#include <sys/dir.h>
32#include <signal.h>
33
b34976b6 34#include <sys/user.h> /* After a.out.h */
9b818146 35#ifdef SCO5_CORE
252b5132
RH
36#include <sys/paccess.h>
37#include <sys/region.h>
9b818146 38#endif
252b5132
RH
39
40struct sco5_core_struct
41{
42 struct user u;
43};
44
45/* forward declarations */
46
b34976b6
AM
47static asection *make_bfd_asection
48 PARAMS ((bfd *, const char *, flagword, bfd_size_type, bfd_vma, file_ptr));
252b5132
RH
49static struct user *read_uarea PARAMS ((bfd *, int));
50const bfd_target *sco5_core_file_p PARAMS ((bfd *abfd));
51char *sco5_core_file_failing_command PARAMS ((bfd *abfd));
52int sco5_core_file_failing_signal PARAMS ((bfd *abfd));
69d246d9 53#define sco5_core_file_matches_executable_p generic_core_file_matches_executable_p
261b8d08 54#define sco5_core_file_pid _bfd_nocore_core_file_pid
252b5132
RH
55static void swap_abort PARAMS ((void));
56
57static asection *
eea6121a 58make_bfd_asection (abfd, name, flags, size, vma, filepos)
252b5132
RH
59 bfd *abfd;
60 const char *name;
61 flagword flags;
eea6121a 62 bfd_size_type size;
252b5132
RH
63 bfd_vma vma;
64 file_ptr filepos;
65{
66 asection *asect;
67
117ed4f8 68 asect = bfd_make_section_anyway_with_flags (abfd, name, flags);
252b5132
RH
69 if (!asect)
70 return NULL;
eea6121a 71 asect->size = size;
252b5132
RH
72 asect->vma = vma;
73 asect->filepos = filepos;
74 asect->alignment_power = 2;
75
76 return asect;
77}
78
252b5132
RH
79static struct user *
80read_uarea(abfd, filepos)
81 bfd *abfd;
82 int filepos;
83
84{
85 struct sco5_core_struct *rawptr;
dc810e39 86 bfd_size_type amt = sizeof (struct sco5_core_struct);
252b5132 87
dc810e39 88 rawptr = (struct sco5_core_struct *) bfd_zmalloc (amt);
252b5132
RH
89 if (rawptr == NULL)
90 return NULL;
91
92 abfd->tdata.sco5_core_data = rawptr;
93
dc810e39
AM
94 if (bfd_seek (abfd, (file_ptr) filepos, SEEK_SET) != 0
95 || bfd_bread ((void *) &rawptr->u, (bfd_size_type) sizeof rawptr->u,
96 abfd) != sizeof rawptr->u)
252b5132
RH
97 {
98 bfd_set_error (bfd_error_wrong_format);
99 return NULL;
100 }
101
102 /* Sanity check perhaps??? */
7b82c249 103 if (rawptr->u.u_dsize > 0x1000000) /* Remember, it's in pages... */
252b5132
RH
104 {
105 bfd_set_error (bfd_error_wrong_format);
106 return NULL;
107 }
108 if (rawptr->u.u_ssize > 0x1000000)
109 {
110 bfd_set_error (bfd_error_wrong_format);
111 return NULL;
112 }
113 return &rawptr->u;
114}
115
252b5132
RH
116const bfd_target *
117sco5_core_file_p (abfd)
118 bfd *abfd;
119{
120 int coffset_siz, val, nsecs, cheadoffs;
121 int coresize;
122 struct user *u;
123 struct coreoffsets coffsets;
124 struct coresecthead chead;
125 char *secname;
126 flagword flags;
127
33216455 128 /* Read coreoffsets region at end of core (see core(FP)). */
252b5132
RH
129
130 {
252b5132 131 struct stat statbuf;
33216455 132
b677b8c0 133 if (bfd_stat (abfd, &statbuf) < 0)
3dff57e8 134 return NULL;
b677b8c0 135
252b5132
RH
136 coresize = statbuf.st_size;
137 }
138 /* Last long in core is sizeof struct coreoffsets, read it */
dc810e39
AM
139 if ((bfd_seek (abfd, (file_ptr) (coresize - sizeof coffset_siz),
140 SEEK_SET) != 0)
141 || bfd_bread ((void *) &coffset_siz, (bfd_size_type) sizeof coffset_siz,
142 abfd) != sizeof coffset_siz)
252b5132 143 {
7b82c249 144 bfd_set_error (bfd_error_wrong_format);
252b5132
RH
145 return NULL;
146 }
147
148 /* Use it to seek start of coreoffsets region, read it and determine
149 validity */
dc810e39
AM
150 if ((bfd_seek (abfd, (file_ptr) (coresize - coffset_siz), SEEK_SET) != 0)
151 || (bfd_bread ((void *) &coffsets, (bfd_size_type) sizeof coffsets, abfd)
252b5132
RH
152 != sizeof coffsets)
153 || ((coffsets.u_info != 1) && (coffsets.u_info != C_VERSION)))
154 {
7b82c249 155 bfd_set_error (bfd_error_wrong_format);
252b5132
RH
156 return NULL;
157 }
158
7b82c249
KH
159 if (coffsets.u_info == 1)
160 {
252b5132
RH
161 /* Old version, no section heads, read info from user struct */
162
9e7b37b3 163 u = read_uarea (abfd, coffsets.u_user);
252b5132 164 if (! u)
9e7b37b3 165 goto fail;
252b5132 166
7b82c249 167 if (!make_bfd_asection (abfd, ".reg", SEC_HAS_CONTENTS,
b34976b6
AM
168 (bfd_size_type) coffsets.u_usize,
169 0 - (bfd_vma) u->u_ar0,
170 (file_ptr) coffsets.u_user))
9e7b37b3 171 goto fail;
7b82c249
KH
172
173 if (!make_bfd_asection (abfd, ".data",
252b5132 174 SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
b34976b6 175 ((bfd_size_type) u->u_exdata.ux_dsize
252b5132 176 + u->u_exdata.ux_bsize),
b34976b6
AM
177 (bfd_vma) u->u_exdata.ux_datorg,
178 (file_ptr) coffsets.u_data))
9e7b37b3 179 goto fail;
7b82c249
KH
180
181 if (!make_bfd_asection (abfd, ".stack",
182 SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
b34976b6
AM
183 (bfd_size_type) u->u_ssize * NBPC,
184 (bfd_vma) u->u_sub,
185 (file_ptr) coffsets.u_stack))
9e7b37b3 186 goto fail;
252b5132
RH
187
188 return abfd->xvec; /* Done for version 1 */
7b82c249 189 }
252b5132
RH
190
191 /* Immediately before coreoffsets region is a long with offset in core
192 to first coresecthead (CORES_OFFSETS), the long before this is the
193 number of section heads in the list. Read both longs and read the
194 coresecthead and check its validity */
7b82c249
KH
195
196 if ((bfd_seek (abfd,
dc810e39 197 (file_ptr) (coresize - coffset_siz - 2 * sizeof coffset_siz),
252b5132 198 SEEK_SET) != 0)
dc810e39
AM
199 || (bfd_bread ((void *) &nsecs, (bfd_size_type) sizeof nsecs, abfd)
200 != sizeof nsecs)
201 || (bfd_bread ((void *) &cheadoffs, (bfd_size_type) sizeof cheadoffs,
202 abfd) != sizeof cheadoffs)
203 || (bfd_seek (abfd, (file_ptr) cheadoffs, SEEK_SET) != 0)
204 || (bfd_bread ((void *) &chead, (bfd_size_type) sizeof chead, abfd)
205 != sizeof chead)
252b5132
RH
206 || (chead.cs_stype != CORES_OFFSETS)
207 || (chead.cs_x.csx_magic != COREMAGIC_NUMBER))
208 {
209 bfd_set_error (bfd_error_wrong_format);
9e7b37b3 210 goto fail;
252b5132
RH
211 }
212
213 /* OK, we believe you. You're a core file (sure, sure). */
214
215 /* Now loop over all regions and map them */
216 nsecs--; /* We've seen CORES_OFFSETS already */
7b82c249 217 for (; nsecs; nsecs--)
252b5132 218 {
dc810e39
AM
219 if ((bfd_seek (abfd, (file_ptr) chead.cs_hseek, SEEK_SET) != 0)
220 || (bfd_bread ((void *) &chead, (bfd_size_type) sizeof chead, abfd)
221 != sizeof chead))
b34976b6
AM
222 {
223 bfd_set_error (bfd_error_wrong_format);
9e7b37b3 224 goto fail;
b34976b6 225 }
252b5132 226
7b82c249 227 switch (chead.cs_stype)
252b5132
RH
228 {
229 case CORES_MAGIC: /* Core header, check magic */
230 if (chead.cs_x.csx_magic != COREMAGIC_NUMBER)
231 {
232 bfd_set_error (bfd_error_wrong_format);
9e7b37b3 233 goto fail;
252b5132
RH
234 }
235 secname = NULL;
236 nsecs++; /* MAGIC not in section cnt!*/
237 break;
238 case CORES_UAREA: /* U-area, read in tdata */
9e7b37b3 239 u = read_uarea (abfd, chead.cs_sseek);
252b5132 240 if (! u)
9e7b37b3 241 goto fail;
252b5132 242
b34976b6 243 /* This is tricky. As the "register section", we give them
252b5132
RH
244 the entire upage and stack. u.u_ar0 points to where
245 "register 0" is stored. There are two tricks with this,
246 though. One is that the rest of the registers might be
247 at positive or negative (or both) displacements from
248 *u_ar0. The other is that u_ar0 is sometimes an absolute
249 address in kernel memory, and on other systems it is an
250 offset from the beginning of the `struct user'.
7b82c249 251
252b5132
RH
252 As a practical matter, we don't know where the registers
253 actually are, so we have to pass the whole area to GDB.
254 We encode the value of u_ar0 by setting the .regs section
255 up so that its virtual memory address 0 is at the place
256 pointed to by u_ar0 (by setting the vma of the start of
257 the section to -u_ar0). GDB uses this info to locate the
258 regs, using minor trickery to get around the
7b82c249 259 offset-or-absolute-addr problem. */
252b5132
RH
260
261 chead.cs_vaddr = 0 - (bfd_vma) u->u_ar0;
262
b34976b6
AM
263 secname = ".reg";
264 flags = SEC_HAS_CONTENTS;
252b5132 265
b34976b6 266 break;
252b5132
RH
267 case CORES_PREGION: /* A program region, map it */
268 switch (chead.cs_x.csx_preg.csxp_rtyp)
269 {
270 case PT_DATA:
b34976b6 271 secname = ".data"; /* Data region. */
252b5132
RH
272 break;
273 case PT_STACK:
b34976b6 274 secname = ".stack"; /* Stack region. */
252b5132
RH
275 break;
276 case PT_SHMEM:
b34976b6 277 secname = ".shmem"; /* Shared memory */
252b5132
RH
278 break;
279 case PT_LIBDAT:
b34976b6 280 secname = ".libdat"; /* Shared library data */
252b5132
RH
281 break;
282 case PT_V86:
b34976b6 283 secname = ".virt86"; /* Virtual 8086 mode */
252b5132
RH
284 break;
285 case PT_SHFIL:
b34976b6 286 secname = ".mmfile"; /* Memory mapped file */
252b5132
RH
287 break;
288 case PT_XDATA0:
b34976b6 289 secname = ".Xdat0"; /* XENIX data region, virtual 0 */
252b5132
RH
290 break;
291 default:
292 secname = "";
293 }
294 flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
295 break;
296 case CORES_PROC: /* struct proc */
297 case CORES_ITIMER: /* interval timers */
298 case CORES_SCOUTSNAME: /* struct scoutsname */
299 secname = NULL; /* Ignore these */
300 break;
b34976b6
AM
301 default:
302 (*_bfd_error_handler) ("Unhandled SCO core file section type %d\n",
303 chead.cs_stype);
304 continue;
305 }
252b5132
RH
306
307 if (secname
308 && !make_bfd_asection (abfd, secname, flags,
309 (bfd_size_type) chead.cs_vsize,
310 (bfd_vma) chead.cs_vaddr,
311 (file_ptr) chead.cs_sseek))
9e7b37b3 312 goto fail;
252b5132
RH
313
314 }
315
316 return abfd->xvec;
317
9e7b37b3
AM
318 fail:
319 if (abfd->tdata.any)
320 {
321 bfd_release (abfd, abfd->tdata.any);
322 abfd->tdata.any = NULL;
323 }
324 bfd_section_list_clear (abfd);
325 return NULL;
252b5132
RH
326}
327
328char *
329sco5_core_file_failing_command (abfd)
330 bfd *abfd;
331{
332 char *com = abfd->tdata.sco5_core_data->u.u_comm;
333 if (*com)
334 return com;
335 else
336 return NULL;
337}
338
252b5132
RH
339int
340sco5_core_file_failing_signal (ignore_abfd)
341 bfd *ignore_abfd;
342{
7b82c249
KH
343 return ((ignore_abfd->tdata.sco5_core_data->u.u_sysabort != 0)
344 ? ignore_abfd->tdata.sco5_core_data->u.u_sysabort
252b5132
RH
345 : -1);
346}
347
252b5132
RH
348/* If somebody calls any byte-swapping routines, shoot them. */
349static void
7b82c249 350swap_abort ()
252b5132 351{
7b82c249 352 abort (); /* This way doesn't require any declaration for ANSI to fuck up */
252b5132 353}
8ce8c090 354
edeb6e24
AM
355#define NO_GET ((bfd_vma (*) (const void *)) swap_abort)
356#define NO_PUT ((void (*) (bfd_vma, void *)) swap_abort)
357#define NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort)
8ce8c090
AM
358#define NO_GET64 ((bfd_uint64_t (*) (const void *)) swap_abort)
359#define NO_PUT64 ((void (*) (bfd_uint64_t, void *)) swap_abort)
360#define NO_GETS64 ((bfd_int64_t (*) (const void *)) swap_abort)
252b5132
RH
361
362const bfd_target sco5_core_vec =
363 {
364 "sco5-core",
365 bfd_target_unknown_flavour,
b34976b6
AM
366 BFD_ENDIAN_LITTLE, /* target byte order */
367 BFD_ENDIAN_LITTLE, /* target headers byte order */
368 (HAS_RELOC | EXEC_P | /* object flags */
252b5132
RH
369 HAS_LINENO | HAS_DEBUG |
370 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
371 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
b34976b6
AM
372 0, /* symbol prefix */
373 ' ', /* ar_pad_char */
374 16, /* ar_max_namelen */
8ce8c090 375 NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit data */
edeb6e24
AM
376 NO_GET, NO_GETS, NO_PUT, /* 32 bit data */
377 NO_GET, NO_GETS, NO_PUT, /* 16 bit data */
8ce8c090 378 NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit hdrs */
edeb6e24
AM
379 NO_GET, NO_GETS, NO_PUT, /* 32 bit hdrs */
380 NO_GET, NO_GETS, NO_PUT, /* 16 bit hdrs */
b34976b6
AM
381
382 { /* bfd_check_format */
8ce8c090
AM
383 _bfd_dummy_target, /* unknown format */
384 _bfd_dummy_target, /* object file */
385 _bfd_dummy_target, /* archive */
386 sco5_core_file_p /* a core file */
252b5132 387 },
b34976b6 388 { /* bfd_set_format */
8ce8c090
AM
389 bfd_false, bfd_false,
390 bfd_false, bfd_false
252b5132 391 },
b34976b6 392 { /* bfd_write_contents */
8ce8c090
AM
393 bfd_false, bfd_false,
394 bfd_false, bfd_false
252b5132
RH
395 },
396
3f3c5c34
AM
397 BFD_JUMP_TABLE_GENERIC (_bfd_generic),
398 BFD_JUMP_TABLE_COPY (_bfd_generic),
399 BFD_JUMP_TABLE_CORE (sco5),
400 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
401 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
402 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
403 BFD_JUMP_TABLE_WRITE (_bfd_generic),
404 BFD_JUMP_TABLE_LINK (_bfd_nolink),
405 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
252b5132 406
c3c89269 407 NULL,
7b82c249 408
b34976b6 409 (PTR) 0 /* backend_data */
8ce8c090 410 };
This page took 0.655963 seconds and 4 git commands to generate.